longpipe 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,12 +1,42 @@
1
- var w=[{model:"xs",dtype:"f16",resolution:{w:384,h:216},skipFrames:2},{model:"small",dtype:"f16",resolution:{w:384,h:216},skipFrames:1},{model:"medium",dtype:"f16",resolution:{w:512,h:288},skipFrames:1},{model:"large",dtype:"f32",resolution:{w:640,h:360},skipFrames:0},{model:"xl",dtype:"f32",resolution:{w:1280,h:720},skipFrames:0}];var ce=false;function me(a){ce=a;}function x(a){let t=`[longpipe/${a}]`,e=((...r)=>{ce&&console.log(t,...r);});return e.warn=(...r)=>{ce&&console.warn(t,...r);},e}var P=x("adaptive"),Mt=2e3,zt=1e4,Dt=30,Rt=20,Ht=5e3,Lt=.3,Vt=15e3,G=class{constructor(t){this.opts=t;this.currentPresetIdx=w.findIndex(e=>e.model===t.initialModel),this.lastSwapAt=performance.now();}opts;timer=null;currentPresetIdx;lastSwapAt=0;overshootStart=0;headroomStart=0;start(){P(`started; backend=${this.opts.backendKind} initial=${this.opts.initialModel} idx=${this.currentPresetIdx}`),this.timer=setInterval(()=>{this.tick().catch(t=>P("tick failed:",t));},Mt);}stop(){this.timer&&clearInterval(this.timer),this.timer=null;}async tick(){if(typeof document<"u"&&document.hidden)return;let t=performance.now();if(t-this.lastSwapAt<zt)return;let e=await this.opts.getStats();if(e.fps<Rt?(this.overshootStart===0&&(this.overshootStart=t),t-this.overshootStart>=Ht&&this.tryDowngrade(e.fps)):this.overshootStart=0,this.opts.backendKind==="webgpu"&&e.modelMs>0){let r=1e3/Dt*Lt;e.modelMs<r?(this.headroomStart===0&&(this.headroomStart=t),t-this.headroomStart>=Vt&&this.tryUpgrade(e.modelMs,r)):this.headroomStart=0;}}tryDowngrade(t){if(this.currentPresetIdx<=0)return;let e=this.currentPresetIdx-1;P(`downgrade ${w[this.currentPresetIdx].model} \u2192 ${w[e].model} (fps=${t})`),this.swap(e);}tryUpgrade(t,e){if(this.currentPresetIdx>=w.length-1)return;let r=this.currentPresetIdx+1;P(`upgrade ${w[this.currentPresetIdx].model} \u2192 ${w[r].model} (modelMs=${t.toFixed(1)} < ${e.toFixed(1)})`),this.swap(r);}async swap(t){let e=w[t];this.lastSwapAt=performance.now(),this.overshootStart=0,this.headroomStart=0;try{let r=this.opts.buildWeightsUrl(this.opts.weightsBaseUrl,e.model),n=await fetch(r);if(!n.ok)throw new Error(`weights fetch failed: ${n.status} ${r}`);let i=await n.arrayBuffer();await this.opts.swapPreset(e.model,i),this.currentPresetIdx=t,P(`swap to ${e.model} done`);}catch(r){P("swap failed:",r),this.opts.onError?.({message:`adaptive preset swap failed: ${r.message??String(r)}`,source:"adaptive",recoverable:true,cause:r});}}};async function be(a){let t,e=false;if(a instanceof HTMLVideoElement){if(t=a.currentSrc||a.src,!t)throw new Error("background video: HTMLVideoElement has no src")}else if(a instanceof Blob)t=URL.createObjectURL(a),e=true;else if(typeof a=="string")t=a;else throw new Error("background video: unsupported input shape");let r=document.createElement("video");r.crossOrigin="anonymous",r.muted=true,r.loop=true,r.playsInline=true,r.src=t,await new Promise((c,h)=>{r.addEventListener("loadeddata",()=>c(),{once:true}),r.addEventListener("error",()=>h(new Error(`background video: failed to load ${t}`)),{once:true});});try{await r.play();}catch(c){throw new Error(`background video: play() rejected \u2014 ${c.message}`)}let n=new MessageChannel,i=n.port1,o=n.port2,u=false,s=r.requestVideoFrameCallback?.bind(r);if(s){let c=(h,f)=>{if(!u){try{let v=new VideoFrame(r,{timestamp:f.mediaTime*1e6});i.postMessage({frame:v},[v]);}catch{}s(c);}};s(c);}else {let c=()=>{if(!u){try{let h=new VideoFrame(r,{timestamp:performance.now()*1e3});i.postMessage({frame:h},[h]);}catch{}requestAnimationFrame(c);}};requestAnimationFrame(c);}return {port:o,transferList:[o],cleanup:()=>{u=true,i.close(),r.pause(),r.removeAttribute("src"),r.load(),e&&URL.revokeObjectURL(t);}}}var Nt=4,de=8,ve=16;async function E(a){if(typeof a=="string")return a==="none"?{background:{kind:"none"}}:a==="blur"?{background:{kind:"blur",sigma:de}}:{background:{kind:"image",bitmap:await we(a)}};if(a instanceof ImageBitmap)return {background:{kind:"image",bitmap:a}};if(typeof HTMLImageElement<"u"&&a instanceof HTMLImageElement)return {background:{kind:"image",bitmap:await createImageBitmap(a)}};if(typeof HTMLVideoElement<"u"&&a instanceof HTMLVideoElement)return await xe(a);let t=a;if(t.color!==void 0)return {background:{kind:"color",rgb:$t(t.color)}};if(t.blur!==void 0)return {background:{kind:"blur",sigma:jt(t.blur)}};if(t.image!==void 0)return {background:{kind:"image",bitmap:await qt(t.image)}};if(t.video!==void 0)return await xe(t.video);throw new Error(`background: unrecognized input shape \u2014 ${k(a)}`)}async function xe(a){let t;if(typeof a=="string")t=a;else if(typeof HTMLVideoElement<"u"&&a instanceof HTMLVideoElement)t=a;else if(a&&typeof a=="object"&&"data"in a&&"type"in a)t=a.data instanceof Blob?a.data:new Blob([a.data],{type:a.type});else throw new Error(`background.video: unrecognized shape \u2014 ${k(a)}`);let e=await be(t);return {background:{kind:"video",port:e.port},transferList:e.transferList,cleanup:e.cleanup}}function $t(a){if(typeof a=="string"){let t=a.trim().replace(/^#/,"");if(/^[0-9a-fA-F]{6}$/.test(t))return [parseInt(t.slice(0,2),16)/255,parseInt(t.slice(2,4),16)/255,parseInt(t.slice(4,6),16)/255];if(/^[0-9a-fA-F]{3}$/.test(t))return [parseInt(t[0]+t[0],16)/255,parseInt(t[1]+t[1],16)/255,parseInt(t[2]+t[2],16)/255];throw new Error(`background.color: hex must be #rgb or #rrggbb, got ${k(a)}`)}if(!Array.isArray(a)||a.length!==3||!a.every(t=>typeof t=="number"&&Number.isFinite(t)&&t>=0&&t<=1))throw new Error(`background.color: expected hex string or [r, g, b] floats in [0, 1], got ${k(a)}`);return [a[0],a[1],a[2]]}function jt(a){if(a===true)return de;if("sigma"in a){if(typeof a.sigma!="number"||!Number.isFinite(a.sigma)||a.sigma<0)throw new Error(`background.blur.sigma must be a non-negative number, got ${a.sigma}`);return a.sigma}if("strength"in a){let t=a.strength;if(typeof t=="number"){let e=Math.max(0,Math.min(1,t));return ve*e}if(t==="low")return Nt;if(t==="medium")return de;if(t==="high")return ve;throw new Error(`background.blur.strength must be 'low' | 'medium' | 'high' | number, got ${k(t)}`)}throw new Error(`background.blur: must be true, { strength }, or { sigma } \u2014 got ${k(a)}`)}async function qt(a){if(a instanceof ImageBitmap)return a;if(typeof HTMLImageElement<"u"&&a instanceof HTMLImageElement)return createImageBitmap(a);if(typeof a=="string")return we(a);if(a&&typeof a=="object"&&"data"in a&&"type"in a){let t=a.data instanceof Blob?a.data:new Blob([a.data],{type:a.type});return createImageBitmap(t)}throw new Error(`background.image: unrecognized shape \u2014 ${k(a)}`)}async function we(a){let t=await fetch(a);if(!t.ok)throw new Error(`background: failed to load image from ${a} (HTTP ${t.status})`);let e=await t.blob();return createImageBitmap(e)}function k(a){return a===null?"null":typeof a!="object"?typeof a+"("+String(a)+")":`${a.constructor?.name??"Object"} ${JSON.stringify(a).slice(0,80)}`}function ye(){return {input:"MediaStreamTrackProcessor"in self?"mstp":"rvfc-postmessage",output:"MediaStreamTrackGenerator"in self?"mstg":Xt()?"transfer-capture":"bitmap-shuttle"}}var F=null;function Xt(){return F!==null||(F=!/Firefox/.test(navigator.userAgent)),F}function ke(a,t,e){let r=[a];return e==="passthrough"&&r.push(...t.getAudioTracks()),new MediaStream(r)}var A=x("worker_controller"),O=class{worker;listeners=new Map;persistentEvents=new Set;constructor(t){this.worker=t,this.worker.addEventListener("message",this.handleMessage.bind(this)),A("constructed; message listener attached");}handleMessage(t){let{request_id:e,res:r}=t.data,n=this.listeners.get(e);A("msg received: request_id=",e,"handler?",!!n,"persistent?",this.persistentEvents.has(e)),n&&(n(r),this.persistentEvents.has(e)||this.listeners.delete(e));}addPersistentListener(t,e){this.persistentEvents.add(t),this.listeners.set(t,e),A("addPersistentListener:",t);}removePersistentListener(t){this.persistentEvents.delete(t),this.listeners.delete(t);}sendMessage(t,e,r=[]){let n=crypto.randomUUID();return A("sendMessage:",t,"request_id=",n,"transferables=",r.length),new Promise(i=>{this.listeners.set(n,u=>i(u));let o={cmd:t,data:e,request_id:n};this.worker.postMessage(o,r);})}terminate(){this.worker.terminate(),this.listeners.clear(),this.persistentEvents.clear();}};var Ce=x("input-postmessage/main");function Pe(a){let t=document.createElement("video");t.srcObject=a,t.muted=true,t.autoplay=true,t.playsInline=true,t.play().catch(l=>{Ce.warn("video.play() rejected:",l);});let e=t.requestVideoFrameCallback?.bind(t);if(!e)throw new Error("setupPostMessageInput: requestVideoFrameCallback not supported on this browser");let r=new MessageChannel,n=r.port1,i=r.port2,o=false,u=(l,c)=>{if(!o){try{let h=new VideoFrame(t,{timestamp:c.mediaTime*1e6});n.postMessage({frame:h},[h]);}catch(h){Ce.warn("VideoFrame() failed; skipping frame:",h);}e(u);}};return e(u),{port:i,transferList:[i],cleanup:()=>{o=true,n.close(),t.srcObject=null,t.pause();}}}function Te(a){let t=a.getVideoTracks();if(t.length===0)throw new Error("setupMstpInput: input MediaStream has no video tracks");let e=t[0],r=self.MediaStreamTrackProcessor;if(!r)throw new Error("setupMstpInput: MediaStreamTrackProcessor not supported on this browser");let i=new r({track:e}).readable;return {readable:i,transferList:[i],cleanup:()=>{i.cancel().catch(()=>{});}}}function Ue(a,t){switch(a){case "mstp":{let e=Te(t);return {initFields:{inputReadable:e.readable},transferList:e.transferList,cleanup:e.cleanup}}case "rvfc-postmessage":{let e=Pe(t);return {initFields:{inputPort:e.port},transferList:e.transferList,cleanup:e.cleanup}}}}var Kt=x("bitmap-shuttle/main"),Yt=30;function Ie(a,t=Yt){let e=document.createElement("canvas");e.width=a.w,e.height=a.h;let r=e.getContext("bitmaprenderer");if(!r)throw new Error("setupBitmapShuttleOutput: bitmaprenderer context not available");let i=e.captureStream(t).getVideoTracks();if(i.length===0)throw new Error("setupBitmapShuttleOutput: captureStream produced no video tracks");let o=i[0],u=new MessageChannel,s=u.port1,l=u.port2,c=false,h=null,f=()=>{},v=3,I=0;return s.onmessage=B=>{if(c){if(I++,I<v){B.data.bmp.close();return}f();}try{r.transferFromImageBitmap(B.data.bmp);}catch(b){Kt.warn("transferFromImageBitmap failed:",b);}},s.start(),{videoTrack:o,port:l,transferList:[l],startPassthrough:B=>{if(c)return;c=true;let b=document.createElement("video");b.srcObject=B,b.muted=true,b.playsInline=true,b.play().catch(()=>{}),h=b;let W="requestVideoFrameCallback"in b?C=>{b.requestVideoFrameCallback(C);}:C=>{requestAnimationFrame(C);},S=()=>{if(c){if(b.videoWidth===0){W(S);return}createImageBitmap(b,{resizeWidth:e.width,resizeHeight:e.height,resizeQuality:"medium"}).then(C=>{if(!c){C.close();return}try{r.transferFromImageBitmap(C);}catch{}W(S);}).catch(()=>{W(S);});}};W(S),f=()=>{c=false,h&&(h.srcObject=null,h.pause(),h=null);};},cleanup:()=>{f(),s.onmessage=null,s.close(),o.stop();}}}function Be(){let a=self.MediaStreamTrackGenerator;if(!a)throw new Error("setupMstgOutput: MediaStreamTrackGenerator not supported on this browser");let t=new a({kind:"video"}),e=t.writable;return {videoTrack:t,writable:e,transferList:[e],cleanup:()=>{e.abort().catch(()=>{}),t.stop();}}}function We(a,t=30){let e=document.createElement("canvas");e.width=a.w,e.height=a.h;let n=e.captureStream(t).getVideoTracks();if(n.length===0)throw new Error("setupTransferCaptureOutput: captureStream produced no video tracks");let i=n[0],o=e.transferControlToOffscreen();return {videoTrack:i,canvas:o,transferList:[o],cleanup:()=>{i.stop();}}}function Se(a,t){switch(a){case "mstg":{let e=Be();return {videoTrack:e.videoTrack,initFields:{outputWritable:e.writable},transferList:e.transferList,cleanup:e.cleanup}}case "transfer-capture":{let e=We(t);return {videoTrack:e.videoTrack,initFields:{outputCanvas:e.canvas},transferList:e.transferList,cleanup:e.cleanup}}case "bitmap-shuttle":{let e=Ie(t);return {videoTrack:e.videoTrack,initFields:{outputPort:e.port},transferList:e.transferList,startPassthrough:e.startPassthrough,cleanup:e.cleanup}}}}var he=`var ao=Object.defineProperty;var no=(s,t,r)=>t in s?ao(s,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[t]=r;var i=(s,t,r)=>no(s,typeof t!="symbol"?t+"":t,r);var it=!1;function lt(s){it=s}function U(s){let t=\`[longpipe/\${s}]\`,r=((...e)=>{it&&console.log(t,...e)});return r.warn=(...e)=>{it&&console.warn(t,...e)},r}var at=[{model:"xs",dtype:"f16",resolution:{w:384,h:216},skipFrames:2},{model:"small",dtype:"f16",resolution:{w:384,h:216},skipFrames:1},{model:"medium",dtype:"f16",resolution:{w:512,h:288},skipFrames:1},{model:"large",dtype:"f32",resolution:{w:640,h:360},skipFrames:0},{model:"xl",dtype:"f32",resolution:{w:1280,h:720},skipFrames:0}],so={fast:0,balanced:2,quality:4};function V(s){return s==="auto"?null:at[so[s]]}var N=class{constructor(t,r,e,o){i(this,"op");this.op=t.ops.BilinearUpsample(r,{outH:e,outW:o})}get output(){return this.op.output}run(){this.op.run()}};var $=class{constructor(t,r,e,o){i(this,"op");this.op=t.ops.BicubicUpsample(r,{outH:e,outW:o})}get output(){return this.op.output}run(){this.op.run()}};var X=class{constructor(t,r,e,o,a="main"){i(this,"presenter");this.presenter=t.presenters.CompositeSolid(r,e,o,a)}run(){this.presenter.run()}};var j=class{constructor(t,r,e,o,a="main"){i(this,"presenter");this.presenter=t.presenters.CompositeImage(r,e,o,a)}run(){this.presenter.run()}};var q=class{constructor(t,r,e){i(this,"downs",[]);i(this,"ups",[]);let o=uo(e),a=r;for(let n=0;n<o;n++){let u=t.ops.BilinearUpsample(a,{outH:Math.max(1,Math.floor(a.h/2)),outW:Math.max(1,Math.floor(a.w/2))});this.downs.push(u),a=u.output}for(let n=o-1;n>=1;n--){let u=this.downs[n-1].output,p=t.ops.BilinearUpsample(a,{outH:u.h,outW:u.w});this.ups.push(p),a=p.output}}get output(){return this.ups.length>0?this.ups[this.ups.length-1].output:this.downs[0].output}run(){for(let t of this.downs)t.run();for(let t of this.ups)t.run()}};function uo(s){let t=Math.max(1,3*s);return Math.max(2,Math.min(6,Math.round(Math.log2(t))))}var po=.05,K=class{constructor(t,r,e,o,a="main"){i(this,"blur");i(this,"presenter");o<=po?(this.blur=null,this.presenter=t.presenters.CompositeImage(r,e,r,a)):(this.blur=new q(t,r,o),this.presenter=t.presenters.CompositeImageBilinear(r,e,this.blur.output,a))}run(){this.blur?.run(),this.presenter.run()}};var Y=class{constructor(t){i(this,"backend",t);i(this,"displayInput");i(this,"image");i(this,"network",null);i(this,"networkInput",null);i(this,"upscaler",null);i(this,"upscalerMode","bilinear");i(this,"bgConfig",{mode:"solid",color:[0,0,0]});i(this,"compositors",new Map);let r=t.canvas;this.displayInput=t.ops.Input(r.height,r.width),this.image=this.displayInput.output}attachNetwork(t,r,e){this.network=t,this.networkInput=r,this.upscalerMode=e.upscaler,this.bgConfig=e.background,this.upscaler=this.makeUpscaler(),this.compositors.clear()}hasNetwork(){return this.network!==null}setSource(t){this.networkInput?.setSource(t),this.displayInput.setSource(t)}setUpscaler(t){t!==this.upscalerMode&&(this.upscalerMode=t,this.network&&(this.upscaler=this.makeUpscaler(),this.compositors.clear()))}setBackground(t){this.bgConfig=t}run(){this.runModel(),this.runDisplay()}runDisplay(){this.refreshDisplayInput(),this.compositeMain(!1)}runPassthrough(){this.refreshDisplayInput(),this.compositeMain(!0)}compositeMain(t){this.compositeTo("main",t?{mode:"passthrough"}:this.bgConfig)}refreshDisplayInput(){this.displayInput.run()}compositeTo(t,r){let e=this.compositors.get(t);if(e&&lo(e.spec,r)){e.handle.run();return}let o=this.buildCompositor(t,r);this.compositors.set(t,{spec:r,handle:o}),o.run()}runModel(){if(!this.network||!this.networkInput||!this.upscaler)throw new Error("RenderOp.runModel called before attachNetwork");this.networkInput.run(),this.network.run(),this.upscaler.run()}makeUpscaler(){if(!this.network)throw new Error("makeUpscaler called with no network");let{backend:t,network:r,image:e}=this;return this.upscalerMode==="bicubic"?new $(t,r.output,e.h,e.w):new N(t,r.output,e.h,e.w)}buildCompositor(t,r){let{backend:e,image:o}=this;if(r.mode==="passthrough")return e.presenters.CompositePassthrough(o,t);if(!this.upscaler)throw new Error("RenderOp.compositeTo (effect spec) called before attachNetwork");let a=this.upscaler.output;switch(r.mode){case"solid":return new X(e,o,a,r.color,t);case"image":return new j(e,o,a,r.image,t);case"blur":return new K(e,o,a,r.sigma,t)}}};function lo(s,t){if(s.mode!==t.mode)return!1;switch(t.mode){case"passthrough":return!0;case"solid":{let r=s.color;return r[0]===t.color[0]&&r[1]===t.color[1]&&r[2]===t.color[2]}case"blur":return s.sigma===t.sigma;case"image":return s.image===t.image}}var co=s=>typeof s=="object"&&s!==null&&typeof s.offset=="number"&&typeof s.length=="number";function ct(s){if(s.byteLength<4)throw new Error("weights buffer too small");let t=new DataView(s,0,4).getUint32(0,!0),r=4+t;if(s.byteLength<r)throw new Error("weights buffer truncated (header)");let e=new Uint8Array(s,4,t),o=JSON.parse(new TextDecoder().decode(e)),a=o.__dtype__??"f32",n=a==="f16"?2:4;if(r%n!==0)throw new Error(\`payload not \${n}-byte aligned (header=\${t})\`);let u=(s.byteLength-r)/n,p=l=>{if(co(l)){let{offset:c,length:m}=l;if(c+m>u)throw new Error(\`array ref out of range: offset=\${c} length=\${m}\`);let _=r+c*n;return a==="f16"?new Uint16Array(s,_,m):new Float32Array(s,_,m)}if(Array.isArray(l))return l.map(p);if(typeof l=="object"&&l!==null){let c={};for(let m of Object.keys(l))m!=="__dtype__"&&(c[m]=p(l[m]));return c}return l};return p(o)}var R=class{constructor(t,r,e,o){i(this,"inputs");i(this,"output");i(this,"gatesOp");i(this,"candOp");this.inputs=[r,e],this.gatesOp=t.ops.GatesFused(r,e,{weights:o.gates,bias:o.gatesBias}),this.candOp=t.ops.CandUpdateFused(r,e,this.gatesOp.output,{weights:o.cand,bias:o.candBias},o.gamma),this.output=this.candOp.output}run(){this.gatesOp.run(),this.candOp.run()}};function dt(s,t,r,e){let o=e.variant,a=o==="E"||o==="D",n=o==="D",u=t.h,p=t.w,l=[],c=null,m=null,_=0,g=0,x;if(a)if(n){if(!r.down2)throw new Error("variant D requires w.down2");_=Math.round(u/1.25),g=Math.round(p/1.25);let y=s.ops.Conv2d(t,r.down1,{outChannels:e.cHigh,kernel:3,stride:1,padding:1,activation:"relu"});l.push(y),m=y.output;let T=s.ops.BilinearUpsample(m,{outH:_,outW:g});l.push(T),c=T.output;let P=s.ops.DownAdapter(c,r.down2,r.adapter,{stride:2});l.push(P),x=P.output}else{if(!r.down2)throw new Error("variant E requires w.down2");let y=s.ops.Conv2d(t,r.down1,{outChannels:e.cHigh,kernel:3,stride:2,padding:1,activation:"relu"});l.push(y),c=y.output,_=c.h,g=c.w;let T=s.ops.DownAdapter(c,r.down2,r.adapter,{stride:2});l.push(T),x=T.output}else{let y=o==="A"?2:3,T=s.ops.DownAdapter(t,r.down1,r.adapter,{stride:y});l.push(T),x=T.output}return{steps:l,adapted:x,d1:c,dFull:m,midH:_,midW:g}}function mt(s,t,r,e,o,a,n,u,p,l){let c=p.variant,m=c==="E"||c==="D",_=c==="D",g=[],x=s.ops.ConvExpand(r,u.expandFeat);g.push(x);let y=x.output,T=null;if(l&&p.gruAtBase){let G=new R(s,y,l.hPrev,l.weights);g.push(G),y=G.output,T=G.output}let P;if(m){if(!u.up1Combine)throw new Error("two-stage variant requires w.up1Combine");let G=s.ops.BilinearUpsample(y,{outH:a,outW:n});g.push(G);let ut=s.ops.CatConv6to2(G.output,e,u.up1Combine);g.push(ut);let pt=s.ops.BilinearUpsample(ut.output,{outH:t.h,outW:t.w});g.push(pt),P=pt.output}else{let G=s.ops.BilinearUpsample(y,{outH:t.h,outW:t.w});g.push(G),P=G.output}if(l&&!p.gruAtBase){let G=new R(s,P,l.hPrev,l.weights);g.push(G),P=G.output,T=G.output}let z=_?s.ops.UpFinalSkip(P,o,t,u.upCombine):s.ops.UpFinal(P,t,u.upCombine);return g.push(z),{steps:g,alpha:z.output,hiddenState:T}}var Q=class{constructor(t,r,e,o,a,n,u){i(this,"inputs");i(this,"output");i(this,"hiddenState");i(this,"steps");this.inputs=[r];let p=dt(t,r,o,a),l=new n(t,p.adapted,e),c=t.ops.BilinearUpsample(l.featLowRes,{outH:p.adapted.h,outW:p.adapted.w}),m=mt(t,r,c.output,p.d1,p.dFull,p.midH,p.midW,o,a,u);this.steps=[...p.steps,l,c,...m.steps],this.output=m.alpha,this.hiddenState=m.hiddenState}run(){for(let t of this.steps)t.run()}};var S=class{constructor(t,r,e,o){i(this,"inputs");i(this,"output");i(this,"dwOp");i(this,"pwOp");this.inputs=[r],this.dwOp=t.ops.DepthwiseConv2d(r,e.dw,{kernel:o.kernel,stride:o.stride,padding:o.padding,activation:"relu6"}),this.pwOp=t.ops.Conv2d(this.dwOp.output,e.pw,{outChannels:o.outChannels,kernel:1,stride:1,padding:0,activation:"none"}),this.output=this.pwOp.output}run(){this.dwOp.run(),this.pwOp.run()}};var v=class{constructor(t,r,e,o){i(this,"inputs");i(this,"output");i(this,"expandOp");i(this,"dwOp");i(this,"projOp");this.inputs=[r];let a=o.midChannels!==o.inChannels,n=o.stride===1&&o.inChannels===o.outChannels;this.expandOp=a?t.ops.Conv2d(r,e.expand,{outChannels:o.midChannels,kernel:1,stride:1,padding:0,activation:"relu6"}):null;let u=this.expandOp?this.expandOp.output:r;this.dwOp=t.ops.DepthwiseConv2d(u,e.dw,{kernel:o.kernel,stride:o.stride,padding:o.padding,activation:"relu6"}),this.projOp=n?t.ops.ProjResidual(this.dwOp.output,r,e.proj,{outChannels:o.outChannels}):t.ops.Conv2d(this.dwOp.output,e.proj,{outChannels:o.outChannels,kernel:1,stride:1,padding:0,activation:"none"}),this.output=this.projOp.output}run(){this.expandOp?.run(),this.dwOp.run(),this.projOp.run()}};var B=class{constructor(t,r,e,o,a){i(this,"inputs");i(this,"output");i(this,"upOp");i(this,"concatConvOp");i(this,"conv2Op");this.inputs=[r,e],this.upOp=t.ops.BilinearUpsample(r,{outH:e.h,outW:e.w}),this.concatConvOp=t.ops.ConcatConv2d(this.upOp.output,e,o.conv1,{outChannels:a.outChannels}),this.conv2Op=t.ops.Conv2d(this.concatConvOp.output,o.conv2,{outChannels:a.outChannels,kernel:3,stride:1,padding:1,activation:"relu6"}),this.output=this.conv2Op.output}run(){this.upOp.run(),this.concatConvOp.run(),this.conv2Op.run()}};var J=class{constructor(t,r,e){i(this,"output");i(this,"featLowRes");i(this,"stem");i(this,"s0");i(this,"s1b0");i(this,"s1b1");i(this,"s2b0");i(this,"s2b1");i(this,"s3b0");i(this,"s3b1");i(this,"s3b2");i(this,"s4b0");i(this,"s4b1");i(this,"s4b2");i(this,"bottleneck");i(this,"dec0");i(this,"dec1");i(this,"finalUp");i(this,"outConv");i(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new S(t,this.stem.output,e.encoder.s0,{outChannels:16,kernel:3,stride:1,padding:1}),this.s1b0=new v(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new v(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new v(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new v(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new v(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new v(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new v(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new v(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new v(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new v(t,this.s4b1.output,e.encoder.s4[2],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.bottleneck=t.ops.Conv2d(this.s4b2.output,e.bottleneck,{outChannels:128,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new B(t,this.bottleneck.output,this.s2b1.output,e.decoder.blocks[0],{outChannels:64}),this.dec1=new B(t,this.dec0.output,this.s1b1.output,e.decoder.blocks[1],{outChannels:32}),this.finalUp=t.ops.UpsampleConv1x1(this.dec1.output,e.decoder.finalUpsample,{outH:this.dec1.output.h*2,outW:this.dec1.output.w*2,outChannels:32,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run(),this.s1b0.run(),this.s1b1.run(),this.s2b0.run(),this.s2b1.run(),this.s3b0.run(),this.s3b1.run(),this.s3b2.run(),this.s4b0.run(),this.s4b1.run(),this.s4b2.run(),this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var Z=class{constructor(t,r,e){i(this,"output");i(this,"featLowRes");i(this,"stem");i(this,"s0");i(this,"s1b0");i(this,"s1b1");i(this,"s2b0");i(this,"s2b1");i(this,"s3b0");i(this,"s3b1");i(this,"s3b2");i(this,"s4b0");i(this,"s4b1");i(this,"s4b2");i(this,"s5b0");i(this,"s5b1");i(this,"s5b2");i(this,"s5b3");i(this,"s6b0");i(this,"bottleneck");i(this,"dec0");i(this,"dec1");i(this,"dec2");i(this,"finalUp");i(this,"outConv");i(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new S(t,this.stem.output,e.encoder.s0,{outChannels:16,kernel:3,stride:1,padding:1}),this.s1b0=new v(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new v(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new v(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new v(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new v(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new v(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new v(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new v(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new v(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new v(t,this.s4b1.output,e.encoder.s4[2],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s5b0=new v(t,this.s4b2.output,e.encoder.s5[0],{inChannels:112,midChannels:672,outChannels:192,kernel:5,stride:2,padding:"same"}),this.s5b1=new v(t,this.s5b0.output,e.encoder.s5[1],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b2=new v(t,this.s5b1.output,e.encoder.s5[2],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b3=new v(t,this.s5b2.output,e.encoder.s5[3],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s6b0=new v(t,this.s5b3.output,e.encoder.s6[0],{inChannels:192,midChannels:1152,outChannels:320,kernel:3,stride:1,padding:1}),this.bottleneck=t.ops.Conv2d(this.s6b0.output,e.bottleneck,{outChannels:128,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new B(t,this.bottleneck.output,this.s4b2.output,e.decoder.blocks[0],{outChannels:64}),this.dec1=new B(t,this.dec0.output,this.s2b1.output,e.decoder.blocks[1],{outChannels:32}),this.dec2=new B(t,this.dec1.output,this.s1b1.output,e.decoder.blocks[2],{outChannels:16}),this.finalUp=t.ops.UpsampleConv1x1(this.dec2.output,e.decoder.finalUpsample,{outH:this.dec2.output.h*2,outW:this.dec2.output.w*2,outChannels:16,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run(),this.s1b0.run(),this.s1b1.run(),this.s2b0.run(),this.s2b1.run(),this.s3b0.run(),this.s3b1.run(),this.s3b2.run(),this.s4b0.run(),this.s4b1.run(),this.s4b2.run(),this.s5b0.run(),this.s5b1.run(),this.s5b2.run(),this.s5b3.run(),this.s6b0.run(),this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.dec2.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var nt=[[{in:24,mid:144,out:32,k:3,s:2},{in:32,mid:192,out:32,k:3,s:1},{in:32,mid:192,out:32,k:3,s:1},{in:32,mid:192,out:32,k:3,s:1}],[{in:32,mid:192,out:56,k:5,s:2},{in:56,mid:336,out:56,k:5,s:1},{in:56,mid:336,out:56,k:5,s:1},{in:56,mid:336,out:56,k:5,s:1}],[{in:56,mid:336,out:112,k:3,s:2},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1}],[{in:112,mid:672,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1}],[{in:160,mid:960,out:272,k:5,s:2},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1}],[{in:272,mid:1632,out:448,k:3,s:1}]],ee=class{constructor(t,r,e){i(this,"output");i(this,"featLowRes");i(this,"stem");i(this,"s0");i(this,"stages");i(this,"bottleneck");i(this,"dec0");i(this,"dec1");i(this,"dec2");i(this,"finalUp");i(this,"outConv");i(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new S(t,this.stem.output,e.encoder.s0,{outChannels:24,kernel:3,stride:1,padding:1});let o=[e.encoder.s1,e.encoder.s2,e.encoder.s3,e.encoder.s4,e.encoder.s5,e.encoder.s6];this.stages=[];let a=this.s0.output;for(let m=0;m<nt.length;m++){let _=[];for(let g=0;g<nt[m].length;g++){let x=nt[m][g],y=new v(t,a,o[m][g],{inChannels:x.in,midChannels:x.mid,outChannels:x.out,kernel:x.k,stride:x.s,padding:x.s===2?"same":(x.k-1)/2});_.push(y),a=y.output}this.stages.push(_)}let n=m=>this.stages[m][this.stages[m].length-1].output,u=n(0),p=n(1),l=n(3),c=n(5);this.bottleneck=t.ops.Conv2d(c,e.bottleneck,{outChannels:256,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new B(t,this.bottleneck.output,l,e.decoder.blocks[0],{outChannels:128}),this.dec1=new B(t,this.dec0.output,p,e.decoder.blocks[1],{outChannels:64}),this.dec2=new B(t,this.dec1.output,u,e.decoder.blocks[2],{outChannels:32}),this.finalUp=t.ops.UpsampleConv1x1(this.dec2.output,e.decoder.finalUpsample,{outH:this.dec2.output.h*2,outW:this.dec2.output.w*2,outChannels:32,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run();for(let t of this.stages)for(let r of t)r.run();this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.dec2.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var ft=J,ht=Z,mo=ee,E={xs:{base:ft,wrapper:{variant:"B",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:384,h:216},baseRes:{w:128,h:72}},small:{base:ft,wrapper:{variant:"A",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:384,h:216},baseRes:{w:192,h:108}},medium:{base:ht,wrapper:{variant:"A",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:512,h:288},baseRes:{w:256,h:144}},large:{base:ht,wrapper:{variant:"D",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:640,h:360},baseRes:{w:256,h:144}},xl:{base:mo,wrapper:{variant:"E",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:1280,h:720},baseRes:{w:320,h:180}}};var fo=15,ho=5,gt=1e3,te=class{constructor(t){i(this,"canvas");i(this,"backend");i(this,"backendKind");i(this,"topology");i(this,"preset",null);i(this,"enabled");i(this,"currentBackground");i(this,"modelTimingCounter",0);i(this,"renderOp");i(this,"tierModel",null);i(this,"hPrev",null);i(this,"bgImageInputs",new Map);i(this,"bgVideoInputs",new Map);i(this,"bgVideoPorts",new Map);i(this,"previewCanvas",null);i(this,"previewCtx",null);i(this,"previewBg",null);i(this,"previewEffectSpec",null);i(this,"previewIntervalMs",1e3/fo);i(this,"lastPreviewAt",0);i(this,"skipCounter",0);i(this,"framesRenderedAt",[]);i(this,"modelRunSamples",[]);i(this,"displayRunSamples",[]);i(this,"skippedCount",0);this.backend=t.backend,this.backendKind=t.backendKind,this.canvas=t.canvas,this.enabled=t.enabled,this.currentBackground=t.background,this.topology=t.topology,this.renderOp=new Y(this.backend)}process(t){this.renderOp.setSource(t);let r=performance.now(),e=this.renderOp.hasNetwork(),o=this.enabled&&e&&this.currentBackground.kind!=="none",a=this.isPreviewTick(r),n=a&&e&&this.previewBg!==null&&this.previewBg.kind!=="none",u=!1;o&&(this.shouldRunModel()?(this.runModelOnce(),u=!0):this.skippedCount++),!u&&n&&(this.runModelOnce(),u=!0);let p=performance.now();a&&this.previewCanvas?(this.backendKind==="webgl"?this.compositePreviewWebGL(o,n):(this.compositeMain(o),this.renderOp.compositeTo("preview",this.previewSpec(n))),this.lastPreviewAt=r):this.compositeMain(o),this.displayRunSamples.push({ts:performance.now(),ms:performance.now()-p}),this.trimSamples(this.displayRunSamples),this.framesRenderedAt.push(performance.now()),this.trim(this.framesRenderedAt)}compositeMain(t){t?this.renderOp.runDisplay():this.renderOp.runPassthrough()}compositePreviewWebGL(t,r){this.renderOp.refreshDisplayInput(),this.renderOp.compositeTo("preview",this.previewSpec(r));let e=this.canvas.transferToImageBitmap();this.previewCtx.transferFromImageBitmap(e),this.renderOp.compositeMain(!t)}previewSpec(t){return t&&this.previewEffectSpec?this.previewEffectSpec:{mode:"passthrough"}}runModelOnce(){let t=performance.now();this.renderOp.runModel(),this.hPrev&&this.tierModel?.hiddenState&&this.backend.copyTensor(this.tierModel.hiddenState,this.hPrev),this.backendKind==="webgpu"&&this.modelTimingCounter%ho===0&&this.backend.sync().then(()=>{this.modelRunSamples.push({ts:performance.now(),ms:performance.now()-t}),this.trimSamples(this.modelRunSamples)}).catch(()=>{}),this.modelTimingCounter++}isPreviewTick(t){return!this.previewCanvas||this.previewBg===null||!this.enabled?!1:t-this.lastPreviewAt>=this.previewIntervalMs}shouldRunModel(){return this.skipCounter===0?(this.skipCounter=this.preset?.skipFrames??0,!0):(this.skipCounter--,!1)}setBackground(t){this.currentBackground=t,this.renderOp.setBackground(this.translateBackgroundFor("main",t))}setEnabled(t){this.enabled=t}attachPreview(t){if(t.width=this.canvas.width,t.height=this.canvas.height,this.previewCanvas=t,this.backendKind==="webgpu")this.backend.attachCanvas("preview",t);else{let r=t.getContext("bitmaprenderer");if(!r)throw new Error("renderer: failed to get bitmaprenderer context for preview canvas");this.previewCtx=r}}setPreview(t,r){this.previewBg=t,this.previewEffectSpec=t.kind==="none"?null:this.translateBackgroundFor("preview",t),r?.fps&&r.fps>0&&(this.previewIntervalMs=1e3/r.fps),this.lastPreviewAt=0}clearPreview(){this.previewBg=null,this.previewEffectSpec=null;let t=this.bgVideoPorts.get("preview");t&&(t.close(),this.bgVideoPorts.delete("preview"))}setPreset(t,r){let e=E[t.model];if(!e)throw new Error(\`renderer: no TIER_CONFIG entry for model '\${t.model}'\`);let o=ct(r),a=this.backend.ops.Input(e.canvasRes.h,e.canvasRes.w),n,u=null;if(e.hasGru){let l=e.wrapper.gruAtBase?e.baseRes:e.canvasRes;u=this.backend.tensor(l.h,l.w,4,new Float32Array(l.h*l.w*4)),n={weights:o.gru,hPrev:u}}let p=new Q(this.backend,a.output,o.base,o.wrapper,e.wrapper,e.base,n);this.renderOp.attachNetwork(p,a,{upscaler:"bilinear",background:this.translateBackgroundFor("main",this.currentBackground)}),this.tierModel=p,this.hPrev=u,this.preset=t,this.skipCounter=0}destroy(){for(let t of this.bgVideoPorts.values())t.close();this.bgVideoPorts.clear(),this.backend.destroy()}getStats(){let t=performance.now();return this.trimRecent(this.framesRenderedAt,t),this.trimSamplesAt(this.modelRunSamples,t),this.trimSamplesAt(this.displayRunSamples,t),{fps:this.framesRenderedAt.length,modelFps:this.modelRunSamples.length,modelMs:_t(this.modelRunSamples.map(r=>r.ms)),displayMs:_t(this.displayRunSamples.map(r=>r.ms)),skipped:this.skippedCount,preset:this.preset?.model??"boot",skipFrames:this.preset?.skipFrames??0,enabled:this.enabled,inputPath:this.topology.input,outputPath:this.topology.output}}translateBackgroundFor(t,r){let e=this.bgVideoPorts.get(t);switch(r.kind!=="video"&&e&&(e.close(),this.bgVideoPorts.delete(t)),r.kind){case"none":return{mode:"solid",color:[0,0,0]};case"color":return{mode:"solid",color:r.rgb};case"blur":return{mode:"blur",sigma:r.sigma};case"image":{let o=this.bgInputFor(this.bgImageInputs,t);return o.setSource(r.bitmap),o.run(),{mode:"image",image:o.output}}case"video":{let o=this.bgInputFor(this.bgVideoInputs,t);return e&&e.close(),this.bgVideoPorts.set(t,r.port),r.port.onmessage=a=>{let n=a.data.frame;try{o.setSource(n),o.run()}finally{n.close()}},r.port.start?.(),{mode:"image",image:o.output}}}}bgInputFor(t,r){let e=t.get(r);return e||(e=this.backend.ops.Input(this.canvas.height,this.canvas.width),t.set(r,e)),e}trim(t){t.length>240&&t.splice(0,t.length-240)}trimSamples(t){t.length>240&&t.splice(0,t.length-240)}trimRecent(t,r){let e=r-gt,o=0;for(;o<t.length&&t[o]<e;)o++;o>0&&t.splice(0,o)}trimSamplesAt(t,r){let e=r-gt,o=0;for(;o<t.length&&t[o].ts<e;)o++;o>0&&t.splice(0,o)}};function _t(s){if(s.length===0)return 0;let t=s.slice().sort((e,o)=>e-o),r=t.length>>1;return t.length%2?t[r]:(t[r-1]+t[r])/2}var O=new Float32Array(1),M=new Uint32Array(O.buffer);function go(s){O[0]=s;let t=M[0],r=t>>>16&32768,e=t&2147483647,o=(e>>>23)-127+15;if((t&2139095040)===2139095040)return(t&8388607)!==0?r|32256:r|31744;if(o>=31)return r|31744;if(o<=0){if(o<-10)return r;let l=e&8388607|8388608,c=14-o,m=l>>>c,_=l>>>c-1&1,g=(l&(1<<c-1)-1)!==0?1:0;return _&&(g||m&1)&&(m+=1),r|m}let a=e>>>13&1023,n=e>>>12&1,u=(e&4095)!==0?1:0,p=o<<10|a;return n&&(u||a&1)&&(p+=1,(p>>>10&31)===31)?r|31744:r|p}function _o(s){let t=(s&32768)<<16,r=(s&31744)>>>10,e=s&1023;if(r===0){if(e===0)return M[0]=t,O[0];let o=e,a=1;for(;(o&1024)===0;)o<<=1,a-=1;return o&=1023,M[0]=t|a+127-15<<23|o<<13,O[0]}return r===31?(M[0]=t|2139095040|e<<13,O[0]):(M[0]=t|r+127-15<<23|e<<13,O[0])}function re(s){let t=new Uint16Array(s.length);for(let r=0;r<s.length;r++)t[r]=go(s[r]);return t}function I(s){let t=new Float32Array(s.length);for(let r=0;r<s.length;r++)t[r]=_o(s[r]);return t}var f=class{constructor(t){i(this,"backend",t);i(this,"shader","");i(this,"pipeline");i(this,"bindGroup");i(this,"uniformDefs",[]);i(this,"uniformBuffers",{})}createUniform(t,r){this.uniformDefs.push({name:t,type:r})}setUniform(t,r){let e=this.backend.device.createBuffer({size:r.byteLength,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});r instanceof Uint32Array?new Uint32Array(e.getMappedRange()).set(r):new Float32Array(e.getMappedRange()).set(r),e.unmap(),this.uniformBuffers[t]=e}defaultBindGroup(){let t=[],r=0;for(let e of this.inputs)t.push({binding:r++,resource:{buffer:e.buffer}});for(let e of this.weights)t.push({binding:r++,resource:{buffer:e.buffer}});for(let e of this.uniformDefs)t.push({binding:r++,resource:{buffer:this.uniformBuffers[e.name]}});return t.push({binding:r,resource:{buffer:this.output.buffer}}),this.backend.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:t})}defaultSetup(){let t=this.backend.device.createShaderModule({code:this.shader});this.pipeline=this.backend.device.createComputePipeline({layout:"auto",compute:{module:t,entryPoint:"main"}}),this.bindGroup=this.defaultBindGroup()}run(){let t=this.backend.device.createCommandEncoder(),r=t.beginComputePass();r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.dispatchWorkgroups(...this.dispatch),r.end(),this.backend.device.queue.submit([t.finish()])}};var bt=\`// Conv2d, output-channel-blocked (K=4) \\u2014 drop-in replacement for conv2d.wgsl.
1
+ var y=[{model:"xs",dtype:"f16",resolution:{w:384,h:216},skipFrames:2},{model:"small",dtype:"f16",resolution:{w:384,h:216},skipFrames:1},{model:"medium",dtype:"f16",resolution:{w:512,h:288},skipFrames:1},{model:"large",dtype:"f32",resolution:{w:640,h:360},skipFrames:0},{model:"xl",dtype:"f32",resolution:{w:1280,h:720},skipFrames:0}];var _e=false;function Te(a){_e=a;}function x(a){let t=`[longpipe/${a}]`,e=((...r)=>{_e&&console.log(t,...r);});return e.warn=(...r)=>{_e&&console.warn(t,...r);},e}var T=x("adaptive"),sr=2e3,ur=1e4,pr=30,lr=20,cr=5e3,dr=.3,fr=15e3,G=class{constructor(t){this.opts=t;this.currentPresetIdx=y.findIndex(e=>e.model===t.initialModel),this.lastSwapAt=performance.now();}opts;timer=null;currentPresetIdx;lastSwapAt=0;overshootStart=0;headroomStart=0;start(){T(`started; backend=${this.opts.backendKind} initial=${this.opts.initialModel} idx=${this.currentPresetIdx}`),this.timer=setInterval(()=>{this.tick().catch(t=>T("tick failed:",t));},sr);}stop(){this.timer&&clearInterval(this.timer),this.timer=null;}async tick(){if(typeof document<"u"&&document.hidden)return;let t=performance.now();if(t-this.lastSwapAt<ur)return;let e=await this.opts.getStats();if(e.fps<lr?(this.overshootStart===0&&(this.overshootStart=t),t-this.overshootStart>=cr&&this.tryDowngrade(e.fps)):this.overshootStart=0,this.opts.backendKind==="webgpu"&&e.modelMs>0){let r=1e3/pr*dr;e.modelMs<r?(this.headroomStart===0&&(this.headroomStart=t),t-this.headroomStart>=fr&&this.tryUpgrade(e.modelMs,r)):this.headroomStart=0;}}tryDowngrade(t){if(this.currentPresetIdx<=0)return;let e=this.currentPresetIdx-1;T(`downgrade ${y[this.currentPresetIdx].model} \u2192 ${y[e].model} (fps=${t})`),this.swap(e);}tryUpgrade(t,e){if(this.currentPresetIdx>=y.length-1)return;let r=this.currentPresetIdx+1;T(`upgrade ${y[this.currentPresetIdx].model} \u2192 ${y[r].model} (modelMs=${t.toFixed(1)} < ${e.toFixed(1)})`),this.swap(r);}async swap(t){let e=y[t];this.lastSwapAt=performance.now(),this.overshootStart=0,this.headroomStart=0;try{let r=await this.opts.fetchWeights(e.model);await this.opts.swapPreset(e.model,r),this.currentPresetIdx=t,T(`swap to ${e.model} done`);}catch(r){T("swap failed:",r),this.opts.onError?.({message:`adaptive preset swap failed: ${r.message??String(r)}`,source:"adaptive",recoverable:true,cause:r});}}};async function Ue(a){let t,e=false;if(a instanceof HTMLVideoElement){if(t=a.currentSrc||a.src,!t)throw new Error("background video: HTMLVideoElement has no src")}else if(a instanceof Blob)t=URL.createObjectURL(a),e=true;else if(typeof a=="string")t=a;else throw new Error("background video: unsupported input shape");let r=document.createElement("video");r.crossOrigin="anonymous",r.muted=true,r.loop=true,r.playsInline=true,r.src=t,await new Promise((c,f)=>{r.addEventListener("loadeddata",()=>c(),{once:true}),r.addEventListener("error",()=>f(new Error(`background video: failed to load ${t}`)),{once:true});});try{await r.play();}catch(c){throw new Error(`background video: play() rejected \u2014 ${c.message}`)}let n=new MessageChannel,i=n.port1,o=n.port2,s=false,u=r.requestVideoFrameCallback?.bind(r);if(u){let c=(f,h)=>{if(!s){try{let m=new VideoFrame(r,{timestamp:h.mediaTime*1e6});i.postMessage({frame:m},[m]);}catch{}u(c);}};u(c);}else {let c=()=>{if(!s){try{let f=new VideoFrame(r,{timestamp:performance.now()*1e3});i.postMessage({frame:f},[f]);}catch{}requestAnimationFrame(c);}};requestAnimationFrame(c);}return {port:o,transferList:[o],cleanup:()=>{s=true,i.close(),r.pause(),r.removeAttribute("src"),r.load(),e&&URL.revokeObjectURL(t);}}}var hr=4,be=8,We=16;async function F(a){if(typeof a=="string")return a==="none"?{background:{kind:"none"}}:a==="blur"?{background:{kind:"blur",sigma:be}}:{background:{kind:"image",bitmap:await Be(a)}};if(a instanceof ImageBitmap)return {background:{kind:"image",bitmap:a}};if(typeof HTMLImageElement<"u"&&a instanceof HTMLImageElement)return {background:{kind:"image",bitmap:await createImageBitmap(a)}};if(typeof HTMLVideoElement<"u"&&a instanceof HTMLVideoElement)return await Ie(a);let t=a;if(t.color!==void 0)return {background:{kind:"color",rgb:gr(t.color)}};if(t.blur!==void 0)return {background:{kind:"blur",sigma:mr(t.blur)}};if(t.image!==void 0)return {background:{kind:"image",bitmap:await _r(t.image)}};if(t.video!==void 0)return await Ie(t.video);throw new Error(`background: unrecognized input shape \u2014 ${P(a)}`)}async function Ie(a){let t;if(typeof a=="string")t=a;else if(typeof HTMLVideoElement<"u"&&a instanceof HTMLVideoElement)t=a;else if(a&&typeof a=="object"&&"data"in a&&"type"in a)t=a.data instanceof Blob?a.data:new Blob([a.data],{type:a.type});else throw new Error(`background.video: unrecognized shape \u2014 ${P(a)}`);let e=await Ue(t);return {background:{kind:"video",port:e.port},transferList:e.transferList,cleanup:e.cleanup}}function gr(a){if(typeof a=="string"){let t=a.trim().replace(/^#/,"");if(/^[0-9a-fA-F]{6}$/.test(t))return [parseInt(t.slice(0,2),16)/255,parseInt(t.slice(2,4),16)/255,parseInt(t.slice(4,6),16)/255];if(/^[0-9a-fA-F]{3}$/.test(t))return [parseInt(t[0]+t[0],16)/255,parseInt(t[1]+t[1],16)/255,parseInt(t[2]+t[2],16)/255];throw new Error(`background.color: hex must be #rgb or #rrggbb, got ${P(a)}`)}if(!Array.isArray(a)||a.length!==3||!a.every(t=>typeof t=="number"&&Number.isFinite(t)&&t>=0&&t<=1))throw new Error(`background.color: expected hex string or [r, g, b] floats in [0, 1], got ${P(a)}`);return [a[0],a[1],a[2]]}function mr(a){if(a===true)return be;if("sigma"in a){if(typeof a.sigma!="number"||!Number.isFinite(a.sigma)||a.sigma<0)throw new Error(`background.blur.sigma must be a non-negative number, got ${a.sigma}`);return a.sigma}if("strength"in a){let t=a.strength;if(typeof t=="number"){let e=Math.max(0,Math.min(1,t));return We*e}if(t==="low")return hr;if(t==="medium")return be;if(t==="high")return We;throw new Error(`background.blur.strength must be 'low' | 'medium' | 'high' | number, got ${P(t)}`)}throw new Error(`background.blur: must be true, { strength }, or { sigma } \u2014 got ${P(a)}`)}async function _r(a){if(a instanceof ImageBitmap)return a;if(typeof HTMLImageElement<"u"&&a instanceof HTMLImageElement)return createImageBitmap(a);if(typeof a=="string")return Be(a);if(a&&typeof a=="object"&&"data"in a&&"type"in a){let t=a.data instanceof Blob?a.data:new Blob([a.data],{type:a.type});return createImageBitmap(t)}throw new Error(`background.image: unrecognized shape \u2014 ${P(a)}`)}async function Be(a){let t=await fetch(a);if(!t.ok)throw new Error(`background: failed to load image from ${a} (HTTP ${t.status})`);let e=await t.blob();return createImageBitmap(e)}function P(a){return a===null?"null":typeof a!="object"?typeof a+"("+String(a)+")":`${a.constructor?.name??"Object"} ${JSON.stringify(a).slice(0,80)}`}function Se(){return {input:"MediaStreamTrackProcessor"in self?"mstp":"rvfc-postmessage",output:"MediaStreamTrackGenerator"in self?"mstg":br()?"transfer-capture":"bitmap-shuttle"}}var A=null;function br(){return A!==null||(A=!/Firefox/.test(navigator.userAgent)),A}function Ee(a){return a==="denoise"?{mode:"denoise",denoise:{}}:typeof a=="object"?{mode:"denoise",denoise:a.denoise}:{mode:a}}function Ge(a,t,e,r){let n=[a];return e.mode==="passthrough"?n.push(...t.getAudioTracks()):e.mode==="denoise"&&r&&n.push(r),new MediaStream(n)}var U={rnnoise:{wasm:"rnnoise.wasm",weights:null,scaleIn:32768,scaleOut:30517578125e-15,needsSimd:false,exports:{malloc:"malloc",create:"rn_create",process:"rn_process"}},dfn:{wasm:"dfn.wasm",weights:"dfn_weights.pack",scaleIn:1,scaleOut:1,needsSimd:true,exports:{malloc:"df_lite_malloc",create:"df_lite_create",process:"df_lite_process",setBeta:"df_lite_set_beta",setGruLeak:"df_lite_set_gru_leak"}},dfnint8:{wasm:"dfn.wasm",weights:"dfn_weights_int8.pack",scaleIn:1,scaleOut:1,needsSimd:true,exports:{malloc:"df_lite_malloc",create:"df_lite_create_i8",process:"df_lite_process",setBeta:"df_lite_set_beta",setGruLeak:"df_lite_set_gru_leak"}}},vr={high:"dfn",mid:"dfnint8",low:"rnnoise"},xr=["high","mid","low"];function wr(a){return xr.includes(a)}function Fe(a){return wr(a)?vr[a]:a}function Ae(a,t){return `${a.replace(/\/$/,"")}/${t}`}async function Me(a){let t=await fetch(a);if(!t.ok)throw new Error(`audio asset fetch failed: ${t.status} ${a}`);return t.arrayBuffer()}async function Oe(a,t){let e=U[a],[r,n]=await Promise.all([Me(Ae(t,e.wasm)),e.weights?Me(Ae(t,e.weights)):Promise.resolve(null)]);return {wasmBytes:r,weights:n}}function M(){try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,22,1,20,0,253,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11]))}catch{return false}}var yr=1.3,kr=64,Pr=3,Cr=`
2
+ self.onmessage = async (e) => {
3
+ const { wasmUrl, iters, rounds, budget } = e.data
4
+ try {
5
+ const res = await fetch(wasmUrl)
6
+ if (!res.ok) throw new Error(res.status + ' ' + wasmUrl)
7
+ const module = await WebAssembly.compile(await res.arrayBuffer())
8
+ const imports = {}
9
+ for (const im of WebAssembly.Module.imports(module)) {
10
+ ;(imports[im.module] = imports[im.module] || {})
11
+ if (im.kind === 'function') imports[im.module][im.name] = () => 0
12
+ }
13
+ const ex = new WebAssembly.Instance(module, imports).exports
14
+ const best = (fn) => {
15
+ fn(iters) // warm up
16
+ let b = Infinity
17
+ for (let r = 0; r < rounds; r++) {
18
+ const t = performance.now()
19
+ fn(iters)
20
+ b = Math.min(b, (performance.now() - t) / iters)
21
+ }
22
+ return b
23
+ }
24
+ const dfnMs = best(ex.calibrate_f32)
25
+ const int8Ms = ex.calibrate_i8 ? best(ex.calibrate_i8) : Infinity
26
+ const model = dfnMs <= budget ? 'dfn' : int8Ms <= budget ? 'dfnint8' : 'rnnoise'
27
+ self.postMessage({ model, dfnMs, int8Ms })
28
+ } catch (err) {
29
+ self.postMessage({ error: (err && err.message) || String(err) })
30
+ }
31
+ }
32
+ `;async function De(a,t){if(!M())return "rnnoise";let e=`${a.replace(/\/$/,"")}/${U.dfn.wasm}`,r=null,n=null;try{r=URL.createObjectURL(new Blob([Cr],{type:"application/javascript"})),n=new Worker(r);let i=await new Promise((o,s)=>{n.onmessage=u=>o(u.data),n.onerror=u=>s(new Error(u.message||"probe worker error")),n.postMessage({wasmUrl:e,iters:kr,rounds:Pr,budget:yr});});if(i.error)throw new Error(i.error);return i.model??"rnnoise"}catch(i){return t?.(`audio tier probe failed (${i.message??String(i)}); using rnnoise`),"rnnoise"}finally{n?.terminate(),r&&URL.revokeObjectURL(r);}}var ve='var b=Object.defineProperty;var y=(u,a,i)=>a in u?b(u,a,{enumerable:!0,configurable:!0,writable:!0,value:i}):u[a]=i;var r=(u,a,i)=>y(u,typeof a!="symbol"?a+"":a,i);var f={rnnoise:{wasm:"rnnoise.wasm",weights:null,scaleIn:32768,scaleOut:30517578125e-15,needsSimd:!1,exports:{malloc:"malloc",create:"rn_create",process:"rn_process"}},dfn:{wasm:"dfn.wasm",weights:"dfn_weights.pack",scaleIn:1,scaleOut:1,needsSimd:!0,exports:{malloc:"df_lite_malloc",create:"df_lite_create",process:"df_lite_process",setBeta:"df_lite_set_beta",setGruLeak:"df_lite_set_gru_leak"}},dfnint8:{wasm:"dfn.wasm",weights:"dfn_weights_int8.pack",scaleIn:1,scaleOut:1,needsSimd:!0,exports:{malloc:"df_lite_malloc",create:"df_lite_create_i8",process:"df_lite_process",setBeta:"df_lite_set_beta",setGruLeak:"df_lite_set_gru_leak"}}};var c=4096,m=class extends AudioWorkletProcessor{constructor(i){super();r(this,"cfg");r(this,"mem");r(this,"run");r(this,"state",0);r(this,"inPtr",0);r(this,"outPtr",0);r(this,"setBeta",null);r(this,"setGruLeak",null);r(this,"resample",!1);r(this,"rsPush",null);r(this,"inRs",0);r(this,"outRs",0);r(this,"rsDevInPtr",0);r(this,"rsOutPtr",0);r(this,"enabled");r(this,"model");r(this,"inAcc",new Float32Array(480));r(this,"inFill",0);r(this,"outRing",new Float32Array(4096));r(this,"outRead",0);r(this,"outWrite",0);r(this,"outCount",0);r(this,"primed",!1);r(this,"now");r(this,"times",new Float32Array(256));r(this,"tIdx",0);r(this,"hops",0);r(this,"_f32",null);let o=i.processorOptions;this.model=o.model,this.enabled=o.enabled,this.cfg=f[o.model];try{let t=this.instantiate(o.wasmBytes),e=n=>n?t[n]:void 0;this.mem=t.memory;let s=t[this.cfg.exports.malloc];if(this.run=t[this.cfg.exports.process],this.inPtr=s(480*4),this.outPtr=s(480*4),o.weights?this.state=t[this.cfg.exports.create](this.upload(s,o.weights),o.weights.byteLength):this.state=t[this.cfg.exports.create](),this.setBeta=e(this.cfg.exports.setBeta)??null,this.setGruLeak=e(this.cfg.exports.setGruLeak)??null,this.setBeta&&(o.postFilterBeta??0)>0&&this.setBeta(this.state,o.postFilterBeta),this.setGruLeak&&(o.gruLeak??1)<1&&this.setGruLeak(this.state,o.gruLeak),sampleRate!==48e3){let n=t.df_resampler_create;this.rsPush=t.df_resampler_push??null,n&&this.rsPush?(this.resample=!0,this.inRs=n(sampleRate,48e3),this.outRs=n(48e3,sampleRate),this.rsDevInPtr=s(256*4),this.rsOutPtr=s(c*4)):this.post({type:"error",message:`${o.model} can\'t resample ${sampleRate}\\u219248000 Hz; needs a 48 kHz AudioContext`})}}catch(t){let e=t;this.post({type:"error",message:`denoise init failed: ${e.message??String(t)}${e.stack?`\n`+e.stack:""}`})}this.now=typeof performance<"u"&&performance.now?()=>performance.now():null,this.port.onmessage=t=>{let e=t.data;e.type==="enabled"?this.enabled=e.value:e.type==="config"&&(this.setBeta&&e.postFilterBeta!=null&&this.setBeta(this.state,e.postFilterBeta),this.setGruLeak&&e.gruLeak!=null&&this.setGruLeak(this.state,e.gruLeak))},this.post({type:"ready"})}instantiate(i){var e;let o=new WebAssembly.Module(i),t={};for(let s of WebAssembly.Module.imports(o))t[e=s.module]??(t[e]={}),s.kind==="function"?t[s.module][s.name]=()=>0:s.kind==="memory"?t[s.module][s.name]=new WebAssembly.Memory({initial:256}):s.kind==="table"?t[s.module][s.name]=new WebAssembly.Table({initial:0,element:"anyfunc"}):s.kind==="global"&&(t[s.module][s.name]=new WebAssembly.Global({value:"i32",mutable:!1},0));return new WebAssembly.Instance(o,t).exports}upload(i,o){let t=new Uint8Array(o),e=i(t.length);return new Uint8Array(this.mem.buffer).set(t,e),e}heap(){return(!this._f32||this._f32.buffer!==this.mem.buffer)&&(this._f32=new Float32Array(this.mem.buffer)),this._f32}post(i){this.port.postMessage(i)}pushOut(i){this.outRing[this.outWrite]=i,this.outWrite=(this.outWrite+1)%this.outRing.length,this.outCount++}feed48k(i,o){for(let t=0;t<o;t++)this.inAcc[this.inFill++]=i[t],this.inFill===480&&(this.runHop(),this.inFill=0)}runHop(){let i=this.heap(),o=this.inPtr>>2;for(let e=0;e<480;e++)i[o+e]=this.inAcc[e]*this.cfg.scaleIn;let t=this.now?this.now():0;if(this.run(this.state,this.inPtr,this.outPtr),this.now&&(this.times[this.tIdx=this.tIdx+1&255]=this.now()-t),this.resample&&this.rsPush){let e=this.rsPush(this.outRs,this.outPtr,480,this.rsOutPtr,c);i=this.heap();let s=this.rsOutPtr>>2;for(let n=0;n<e;n++)this.pushOut(i[s+n])}else{let e=this.outPtr>>2;for(let s=0;s<480;s++)this.pushOut(i[e+s]*this.cfg.scaleOut)}++this.hops>=50&&(this.reportStats(),this.hops=0)}reportStats(){let i=Array.from(this.times).filter(e=>e>0).sort((e,s)=>e-s),o=e=>i.length?i[Math.min(i.length-1,Math.floor(e*i.length))]:null,t={model:this.model,p50Ms:this.now?o(.5):null,p95Ms:this.now?o(.95):null,latencyMs:this.outCount/sampleRate*1e3,active:this.enabled&&this.state!==0,sampleRate};this.post({type:"stats",stats:t})}process(i,o){let t=i[0]?.[0],e=o[0]?.[0];if(!e)return!0;let s=e.length;if(!t||!this.enabled||this.state===0)return t&&!this.enabled?e.set(t):e.fill(0),!0;if(this.resample&&this.rsPush){let n=this.heap(),g=this.rsDevInPtr>>2;for(let h=0;h<s;h++)n[g+h]=t[h];let d=this.rsPush(this.inRs,this.rsDevInPtr,s,this.rsOutPtr,c);n=this.heap(),this.feed48k(n.subarray(this.rsOutPtr>>2,(this.rsOutPtr>>2)+d),d)}else this.feed48k(t,s);if(!this.primed)if(this.outCount>=480)this.primed=!0;else return e.fill(0),!0;if(this.outCount>=s)for(let n=0;n<s;n++)e[n]=this.outRing[this.outRead],this.outRead=(this.outRead+1)%this.outRing.length,this.outCount--;else e.fill(0);return!0}};registerProcessor("denoise",m);\n';var Ur=.03,Wr=.995,O=class{constructor(t,e){this.opts=e;this.ctx=new AudioContext({sampleRate:48e3}),this.source=this.ctx.createMediaStreamSource(new MediaStream([t])),this.dest=this.ctx.createMediaStreamDestination(),this.outputTrack=this.dest.stream.getAudioTracks()[0],this.source.connect(this.dest),this.ready=this.init().catch(r=>{this.opts.onError?.(`audio denoise init failed: ${r.message??String(r)}`);});}opts;outputTrack;ready;ctx;source;dest;node=null;model=null;latestStats=null;destroyed=false;resolveExplicit(){let t=Fe(this.opts.model);return U[t].needsSimd&&!M()?(this.opts.onError?.(`${t} needs wasm SIMD; falling back to rnnoise`),"rnnoise"):t}async init(){let t=this.opts.model==="auto"?await De(this.opts.weightsBaseUrl,this.opts.onError):this.resolveExplicit();this.model=t;let e=await Oe(t,this.opts.weightsBaseUrl);if(await this.ctx.audioWorklet.addModule(Ir()),this.destroyed)return;let r={model:t,wasmBytes:e.wasmBytes,weights:e.weights,enabled:this.opts.enabled??true,postFilterBeta:this.opts.postFilterBeta??Ur,gruLeak:this.opts.gruLeak??Wr},n=new AudioWorkletNode(this.ctx,"denoise",{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[1],processorOptions:r});n.port.onmessage=i=>{let o=i.data;o.type==="stats"?this.latestStats=o.stats:o.type==="error"?this.opts.onError?.(o.message):o.type==="ready"&&this.opts.onReady?.();},this.node=n,this.source.disconnect(this.dest),this.source.connect(n).connect(this.dest);}setEnabled(t){this.node?.port.postMessage({type:"enabled",value:t});}setConfig(t){this.node?.port.postMessage({type:"config",...t});}getStats(){return this.latestStats}destroy(){this.destroyed=true;try{this.node?.disconnect();}catch{}try{this.source.disconnect();}catch{}this.ctx.close();}};function Ir(){return URL.createObjectURL(new Blob([ve],{type:"application/javascript"}))}var D=x("worker_controller"),z=class{worker;listeners=new Map;persistentEvents=new Set;constructor(t){this.worker=t,this.worker.addEventListener("message",this.handleMessage.bind(this)),D("constructed; message listener attached");}handleMessage(t){let{request_id:e,res:r}=t.data,n=this.listeners.get(e);D("msg received: request_id=",e,"handler?",!!n,"persistent?",this.persistentEvents.has(e)),n&&(n(r),this.persistentEvents.has(e)||this.listeners.delete(e));}addPersistentListener(t,e){this.persistentEvents.add(t),this.listeners.set(t,e),D("addPersistentListener:",t);}removePersistentListener(t){this.persistentEvents.delete(t),this.listeners.delete(t);}sendMessage(t,e,r=[]){let n=crypto.randomUUID();return D("sendMessage:",t,"request_id=",n,"transferables=",r.length),new Promise(i=>{this.listeners.set(n,s=>i(s));let o={cmd:t,data:e,request_id:n};this.worker.postMessage(o,r);})}terminate(){this.worker.terminate(),this.listeners.clear(),this.persistentEvents.clear();}};var ze=x("input-postmessage/main");function Re(a){let t=document.createElement("video");t.srcObject=a,t.muted=true,t.autoplay=true,t.playsInline=true,t.play().catch(l=>{ze.warn("video.play() rejected:",l);});let e=t.requestVideoFrameCallback?.bind(t);if(!e)throw new Error("setupPostMessageInput: requestVideoFrameCallback not supported on this browser");let r=new MessageChannel,n=r.port1,i=r.port2,o=false,s=(l,c)=>{if(!o){try{let f=new VideoFrame(t,{timestamp:c.mediaTime*1e6});n.postMessage({frame:f},[f]);}catch(f){ze.warn("VideoFrame() failed; skipping frame:",f);}e(s);}};return e(s),{port:i,transferList:[i],cleanup:()=>{o=true,n.close(),t.srcObject=null,t.pause();}}}function He(a){let t=a.getVideoTracks();if(t.length===0)throw new Error("setupMstpInput: input MediaStream has no video tracks");let e=t[0],r=self.MediaStreamTrackProcessor;if(!r)throw new Error("setupMstpInput: MediaStreamTrackProcessor not supported on this browser");let i=new r({track:e}).readable;return {readable:i,transferList:[i],cleanup:()=>{i.cancel().catch(()=>{});}}}function Le(a,t){switch(a){case "mstp":{let e=He(t);return {initFields:{inputReadable:e.readable},transferList:e.transferList,cleanup:e.cleanup}}case "rvfc-postmessage":{let e=Re(t);return {initFields:{inputPort:e.port},transferList:e.transferList,cleanup:e.cleanup}}}}var Br=x("bitmap-shuttle/main"),Sr=30;function Ve(a,t=Sr){let e=document.createElement("canvas");e.width=a.w,e.height=a.h;let r=e.getContext("bitmaprenderer");if(!r)throw new Error("setupBitmapShuttleOutput: bitmaprenderer context not available");let i=e.captureStream(t).getVideoTracks();if(i.length===0)throw new Error("setupBitmapShuttleOutput: captureStream produced no video tracks");let o=i[0],s=new MessageChannel,u=s.port1,l=s.port2,c=false,f=null,h=()=>{},m=3,w=0;return u.onmessage=B=>{if(c){if(w++,w<m){B.data.bmp.close();return}h();}try{r.transferFromImageBitmap(B.data.bmp);}catch(v){Br.warn("transferFromImageBitmap failed:",v);}},u.start(),{videoTrack:o,port:l,transferList:[l],startPassthrough:B=>{if(c)return;c=true;let v=document.createElement("video");v.srcObject=B,v.muted=true,v.playsInline=true,v.play().catch(()=>{}),f=v;let S="requestVideoFrameCallback"in v?C=>{v.requestVideoFrameCallback(C);}:C=>{requestAnimationFrame(C);},E=()=>{if(c){if(v.videoWidth===0){S(E);return}createImageBitmap(v,{resizeWidth:e.width,resizeHeight:e.height,resizeQuality:"medium"}).then(C=>{if(!c){C.close();return}try{r.transferFromImageBitmap(C);}catch{}S(E);}).catch(()=>{S(E);});}};S(E),h=()=>{c=false,f&&(f.srcObject=null,f.pause(),f=null);};},cleanup:()=>{h(),u.onmessage=null,u.close(),o.stop();}}}function Ne(){let a=self.MediaStreamTrackGenerator;if(!a)throw new Error("setupMstgOutput: MediaStreamTrackGenerator not supported on this browser");let t=new a({kind:"video"}),e=t.writable;return {videoTrack:t,writable:e,transferList:[e],cleanup:()=>{e.abort().catch(()=>{}),t.stop();}}}function $e(a,t=30){let e=document.createElement("canvas");e.width=a.w,e.height=a.h;let n=e.captureStream(t).getVideoTracks();if(n.length===0)throw new Error("setupTransferCaptureOutput: captureStream produced no video tracks");let i=n[0],o=e.transferControlToOffscreen();return {videoTrack:i,canvas:o,transferList:[o],cleanup:()=>{i.stop();}}}function je(a,t){switch(a){case "mstg":{let e=Ne();return {videoTrack:e.videoTrack,initFields:{outputWritable:e.writable},transferList:e.transferList,cleanup:e.cleanup}}case "transfer-capture":{let e=$e(t);return {videoTrack:e.videoTrack,initFields:{outputCanvas:e.canvas},transferList:e.transferList,cleanup:e.cleanup}}case "bitmap-shuttle":{let e=Ve(t);return {videoTrack:e.videoTrack,initFields:{outputPort:e.port},transferList:e.transferList,startPassthrough:e.startPassthrough,cleanup:e.cleanup}}}}var xe=`var Fo=Object.defineProperty;var Eo=(u,t,r)=>t in u?Fo(u,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):u[t]=r;var a=(u,t,r)=>Eo(u,typeof t!="symbol"?t+"":t,r);var xt=!1;function Ct(u){xt=u}function S(u){let t=\`[longpipe/\${u}]\`,r=((...e)=>{xt&&console.log(t,...e)});return r.warn=(...e)=>{xt&&console.warn(t,...e)},r}var yt=[{model:"xs",dtype:"f16",resolution:{w:384,h:216},skipFrames:2},{model:"small",dtype:"f16",resolution:{w:384,h:216},skipFrames:1},{model:"medium",dtype:"f16",resolution:{w:512,h:288},skipFrames:1},{model:"large",dtype:"f32",resolution:{w:640,h:360},skipFrames:0},{model:"xl",dtype:"f32",resolution:{w:1280,h:720},skipFrames:0}],Do={fast:0,balanced:2,quality:4};function q(u){return u==="auto"?null:yt[Do[u]]}var K=class{constructor(t,r,e,i){a(this,"op");this.op=t.ops.BilinearUpsample(r,{outH:e,outW:i})}get output(){return this.op.output}run(){this.op.run()}};var Y=class{constructor(t,r,e,i){a(this,"op");this.op=t.ops.BicubicUpsample(r,{outH:e,outW:i})}get output(){return this.op.output}run(){this.op.run()}};var Q=class{constructor(t,r,e,i,o="main"){a(this,"presenter");this.presenter=t.presenters.CompositeSolid(r,e,i,o)}run(){this.presenter.run()}};var J=class{constructor(t,r,e,i,o="main"){a(this,"presenter");this.presenter=t.presenters.CompositeImage(r,e,i,o)}run(){this.presenter.run()}};var Z=class{constructor(t,r,e){a(this,"downs",[]);a(this,"ups",[]);let i=Oo(e),o=r;for(let n=0;n<i;n++){let s=t.ops.BilinearUpsample(o,{outH:Math.max(1,Math.floor(o.h/2)),outW:Math.max(1,Math.floor(o.w/2))});this.downs.push(s),o=s.output}for(let n=i-1;n>=1;n--){let s=this.downs[n-1].output,p=t.ops.BilinearUpsample(o,{outH:s.h,outW:s.w});this.ups.push(p),o=p.output}}get output(){return this.ups.length>0?this.ups[this.ups.length-1].output:this.downs[0].output}run(){for(let t of this.downs)t.run();for(let t of this.ups)t.run()}};function Oo(u){let t=Math.max(1,3*u);return Math.max(2,Math.min(6,Math.round(Math.log2(t))))}var Io=.05,ee=class{constructor(t,r,e,i,o="main"){a(this,"blur");a(this,"presenter");i<=Io?(this.blur=null,this.presenter=t.presenters.CompositeImage(r,e,r,o)):(this.blur=new Z(t,r,i),this.presenter=t.presenters.CompositeImageBilinear(r,e,this.blur.output,o))}run(){this.blur?.run(),this.presenter.run()}};var te=class{constructor(t){a(this,"backend",t);a(this,"displayInput");a(this,"image");a(this,"network",null);a(this,"networkInput",null);a(this,"upscaler",null);a(this,"upscalerMode","bilinear");a(this,"bgConfig",{mode:"solid",color:[0,0,0]});a(this,"compositors",new Map);let r=t.canvas;this.displayInput=t.ops.Input(r.height,r.width),this.image=this.displayInput.output}attachNetwork(t,r,e){this.network=t,this.networkInput=r,this.upscalerMode=e.upscaler,this.bgConfig=e.background,this.upscaler=this.makeUpscaler(),this.compositors.clear()}hasNetwork(){return this.network!==null}setSource(t){this.networkInput?.setSource(t),this.displayInput.setSource(t)}setUpscaler(t){t!==this.upscalerMode&&(this.upscalerMode=t,this.network&&(this.upscaler=this.makeUpscaler(),this.compositors.clear()))}setBackground(t){this.bgConfig=t}run(){this.runModel(),this.runDisplay()}runDisplay(){this.refreshDisplayInput(),this.compositeMain(!1)}runPassthrough(){this.refreshDisplayInput(),this.compositeMain(!0)}compositeMain(t){this.compositeTo("main",t?{mode:"passthrough"}:this.bgConfig)}refreshDisplayInput(){this.displayInput.run()}compositeTo(t,r){let e=this.compositors.get(t);if(e&&Ao(e.spec,r)){e.handle.run();return}let i=this.buildCompositor(t,r);this.compositors.set(t,{spec:r,handle:i}),i.run()}applyAlpha(t){if(!this.network||!this.upscaler)throw new Error("RenderOp.applyAlpha called before attachNetwork");this.backend.copyTensor(t,this.network.output),this.upscaler.run()}runModel(){if(!this.network||!this.networkInput||!this.upscaler)throw new Error("RenderOp.runModel called before attachNetwork");this.networkInput.run(),this.network.run(),this.upscaler.run()}makeUpscaler(){if(!this.network)throw new Error("makeUpscaler called with no network");let{backend:t,network:r,image:e}=this;return this.upscalerMode==="bicubic"?new Y(t,r.output,e.h,e.w):new K(t,r.output,e.h,e.w)}buildCompositor(t,r){let{backend:e,image:i}=this;if(r.mode==="passthrough")return e.presenters.CompositePassthrough(i,t);if(!this.upscaler)throw new Error("RenderOp.compositeTo (effect spec) called before attachNetwork");let o=this.upscaler.output;switch(r.mode){case"solid":return new Q(e,i,o,r.color,t);case"image":return new J(e,i,o,r.image,t);case"blur":return new ee(e,i,o,r.sigma,t)}}};function Ao(u,t){if(u.mode!==t.mode)return!1;switch(t.mode){case"passthrough":return!0;case"solid":{let r=u.color;return r[0]===t.color[0]&&r[1]===t.color[1]&&r[2]===t.color[2]}case"blur":return u.sigma===t.sigma;case"image":return u.image===t.image}}var Mo=u=>typeof u=="object"&&u!==null&&typeof u.offset=="number"&&typeof u.length=="number";function Wt(u){if(u.byteLength<4)throw new Error("weights buffer too small");let t=new DataView(u,0,4).getUint32(0,!0),r=4+t;if(u.byteLength<r)throw new Error("weights buffer truncated (header)");let e=new Uint8Array(u,4,t),i=JSON.parse(new TextDecoder().decode(e)),o=i.__dtype__??"f32",n=o==="f16"?2:4;if(r%n!==0)throw new Error(\`payload not \${n}-byte aligned (header=\${t})\`);let s=(u.byteLength-r)/n,p=l=>{if(Mo(l)){let{offset:c,length:d}=l;if(c+d>s)throw new Error(\`array ref out of range: offset=\${c} length=\${d}\`);let _=r+c*n;return o==="f16"?new Uint16Array(u,_,d):new Float32Array(u,_,d)}if(Array.isArray(l))return l.map(p);if(typeof l=="object"&&l!==null){let c={};for(let d of Object.keys(l))d!=="__dtype__"&&(c[d]=p(l[d]));return c}return l};return p(i)}function Pt(u,t,r,e){let i=e.variant,o=i==="E"||i==="D",n=i==="D",s=t.h,p=t.w,l=[],c=null,d=null,_=0,b=0,g;if(o)if(n){if(!r.down2)throw new Error("variant D requires w.down2");_=Math.round(s/1.25),b=Math.round(p/1.25);let v=u.ops.Conv2d(t,r.down1,{outChannels:e.cHigh,kernel:3,stride:1,padding:1,activation:"relu"});l.push(v),d=v.output;let x=u.ops.BilinearUpsample(d,{outH:_,outW:b});l.push(x),c=x.output;let k=u.ops.DownAdapter(c,r.down2,r.adapter,{stride:2});l.push(k),g=k.output}else{if(!r.down2)throw new Error("variant E requires w.down2");let v=u.ops.Conv2d(t,r.down1,{outChannels:e.cHigh,kernel:3,stride:2,padding:1,activation:"relu"});l.push(v),c=v.output,_=c.h,b=c.w;let x=u.ops.DownAdapter(c,r.down2,r.adapter,{stride:2});l.push(x),g=x.output}else{let v=i==="A"?2:3,x=u.ops.DownAdapter(t,r.down1,r.adapter,{stride:v});l.push(x),g=x.output}return{steps:l,adapted:g,d1:c,dFull:d,midH:_,midW:b}}function Gt(u,t,r,e,i,o,n,s,p){let l=p.variant,c=l==="E"||l==="D",d=l==="D",_=[],b=u.ops.ConvExpand(r,s.expandFeat);_.push(b);let g=b.output,v;if(c){if(!s.up1Combine)throw new Error("two-stage variant requires w.up1Combine");let k=u.ops.BilinearUpsample(g,{outH:o,outW:n});_.push(k);let B=u.ops.CatConv6to2(k.output,e,s.up1Combine);_.push(B);let U=u.ops.BilinearUpsample(B.output,{outH:t.h,outW:t.w});_.push(U),v=U.output}else{let k=u.ops.BilinearUpsample(g,{outH:t.h,outW:t.w});_.push(k),v=k.output}let x=d?u.ops.UpFinalSkip(v,i,t,s.upCombine):u.ops.UpFinal(v,t,s.upCombine);return _.push(x),{steps:_,alpha:x.output}}var re=class{constructor(t,r,e,i,o,n){a(this,"inputs");a(this,"output");a(this,"encoderTaps");a(this,"halfTap");a(this,"steps");this.inputs=[r];let s=Pt(t,r,i,o),p=new n(t,s.adapted,e),l=t.ops.BilinearUpsample(p.featLowRes,{outH:s.adapted.h,outW:s.adapted.w}),c=Gt(t,r,l.output,s.d1,s.dFull,s.midH,s.midW,i,o);this.steps=[...s.steps,p,l,...c.steps],this.output=c.alpha,this.encoderTaps=p.encoderTaps,this.halfTap=p.halfTap}run(){for(let t of this.steps)t.run()}};var Ro=[5,5,3,3],Ho=[2,2,1,1];function oe(u,t,r,e){if(t.h===r.h&&t.w===r.w)return t;let i=u.ops.Crop(t,{outH:r.h,outW:r.w});return e.push(i),i.output}var ie=class{constructor(t,r,e,i,o,n=16,s={}){a(this,"inputs");a(this,"output");a(this,"steps");this.inputs=[r,e,...i,...s.halfTap?[s.halfTap]:[]];let p=[],l=t.ops.ChannelConcat(r,e);p.push(l);let c=t.ops.Conv2d(l.output,o.stem,{outChannels:n,kernel:7,stride:2,padding:3,activation:"relu6"});p.push(c);let d=[],_=c.output;if(s.fuseStem&&s.halfTap){let x=oe(t,s.halfTap,c.output,p),k=t.ops.ChannelConcat(c.output,x);p.push(k),d.push(k.output),_=k.output}for(let x=0;x<i.length;x++){let k=t.ops.Conv2d(_,o.stages[x],{outChannels:n,kernel:Ro[x],stride:2,padding:Ho[x],activation:"relu6"});p.push(k);let B=oe(t,i[x],k.output,p),U=t.ops.ChannelConcat(k.output,B);p.push(U),d.push(U.output),_=U.output}let b=t.ops.Conv2d(d[d.length-1],o.predictBot,{outChannels:4,kernel:3,stride:1,padding:1,activation:"none"});p.push(b);let g=b.output,v=d[d.length-1];for(let x=0;x<d.length-1;x++){let k=d.length-2-x,B=t.ops.BilinearUpsample(v,{outH:v.h*2,outW:v.w*2}),U=t.ops.Conv2d(B.output,o.deconv[x],{outChannels:n,kernel:3,stride:1,padding:1,activation:"relu6"}),X=t.ops.BilinearUpsample(g,{outH:g.h*2,outW:g.w*2});p.push(B,U,X);let vt=oe(t,U.output,d[k],p),z=oe(t,X.output,d[k],p),j=t.ops.ChannelConcat(d[k],vt),D=t.ops.ChannelConcat(j.output,z);p.push(j,D);let V=t.ops.Conv2d(D.output,o.predict[x],{outChannels:4,kernel:3,stride:1,padding:1,activation:"none"});p.push(V),g=V.output,v=D.output}this.output=g,this.steps=p}run(){for(let t of this.steps)t.run()}};var L=class{constructor(t,r,e,i){a(this,"inputs");a(this,"output");a(this,"dwOp");a(this,"pwOp");this.inputs=[r],this.dwOp=t.ops.DepthwiseConv2d(r,e.dw,{kernel:i.kernel,stride:i.stride,padding:i.padding,activation:"relu6"}),this.pwOp=t.ops.Conv2d(this.dwOp.output,e.pw,{outChannels:i.outChannels,kernel:1,stride:1,padding:0,activation:"none"}),this.output=this.pwOp.output}run(){this.dwOp.run(),this.pwOp.run()}};var w=class{constructor(t,r,e,i){a(this,"inputs");a(this,"output");a(this,"expandOp");a(this,"dwOp");a(this,"projOp");this.inputs=[r];let o=i.midChannels!==i.inChannels,n=i.stride===1&&i.inChannels===i.outChannels;this.expandOp=o?t.ops.Conv2d(r,e.expand,{outChannels:i.midChannels,kernel:1,stride:1,padding:0,activation:"relu6"}):null;let s=this.expandOp?this.expandOp.output:r;this.dwOp=t.ops.DepthwiseConv2d(s,e.dw,{kernel:i.kernel,stride:i.stride,padding:i.padding,activation:"relu6"}),this.projOp=n?t.ops.ProjResidual(this.dwOp.output,r,e.proj,{outChannels:i.outChannels}):t.ops.Conv2d(this.dwOp.output,e.proj,{outChannels:i.outChannels,kernel:1,stride:1,padding:0,activation:"none"}),this.output=this.projOp.output}run(){this.expandOp?.run(),this.dwOp.run(),this.projOp.run()}};var G=class{constructor(t,r,e,i,o){a(this,"inputs");a(this,"output");a(this,"upOp");a(this,"concatConvOp");a(this,"conv2Op");this.inputs=[r,e],this.upOp=t.ops.BilinearUpsample(r,{outH:e.h,outW:e.w}),this.concatConvOp=t.ops.ConcatConv2d(this.upOp.output,e,i.conv1,{outChannels:o.outChannels}),this.conv2Op=t.ops.Conv2d(this.concatConvOp.output,i.conv2,{outChannels:o.outChannels,kernel:3,stride:1,padding:1,activation:"relu6"}),this.output=this.conv2Op.output}run(){this.upOp.run(),this.concatConvOp.run(),this.conv2Op.run()}};var ae=class{constructor(t,r,e){a(this,"output");a(this,"featLowRes");a(this,"encoderTaps");a(this,"halfTap");a(this,"stem");a(this,"s0");a(this,"s1b0");a(this,"s1b1");a(this,"s2b0");a(this,"s2b1");a(this,"s3b0");a(this,"s3b1");a(this,"s3b2");a(this,"s4b0");a(this,"s4b1");a(this,"s4b2");a(this,"bottleneck");a(this,"dec0");a(this,"dec1");a(this,"finalUp");a(this,"outConv");a(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new L(t,this.stem.output,e.encoder.s0,{outChannels:16,kernel:3,stride:1,padding:1}),this.s1b0=new w(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new w(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new w(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new w(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new w(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new w(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new w(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new w(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new w(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new w(t,this.s4b1.output,e.encoder.s4[2],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.bottleneck=t.ops.Conv2d(this.s4b2.output,e.bottleneck,{outChannels:128,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new G(t,this.bottleneck.output,this.s2b1.output,e.decoder.blocks[0],{outChannels:64}),this.dec1=new G(t,this.dec0.output,this.s1b1.output,e.decoder.blocks[1],{outChannels:32}),this.finalUp=t.ops.UpsampleConv1x1(this.dec1.output,e.decoder.finalUpsample,{outH:this.dec1.output.h*2,outW:this.dec1.output.w*2,outChannels:32,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.encoderTaps=[this.s1b1.output,this.s2b1.output,this.s4b2.output],this.halfTap=this.s0.output,this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run(),this.s1b0.run(),this.s1b1.run(),this.s2b0.run(),this.s2b1.run(),this.s3b0.run(),this.s3b1.run(),this.s3b2.run(),this.s4b0.run(),this.s4b1.run(),this.s4b2.run(),this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var ne=class{constructor(t,r,e){a(this,"output");a(this,"featLowRes");a(this,"encoderTaps");a(this,"stem");a(this,"s0");a(this,"s1b0");a(this,"s1b1");a(this,"s2b0");a(this,"s2b1");a(this,"s3b0");a(this,"s3b1");a(this,"s3b2");a(this,"s4b0");a(this,"s4b1");a(this,"s4b2");a(this,"s5b0");a(this,"s5b1");a(this,"s5b2");a(this,"s5b3");a(this,"s6b0");a(this,"bottleneck");a(this,"dec0");a(this,"dec1");a(this,"dec2");a(this,"finalUp");a(this,"outConv");a(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new L(t,this.stem.output,e.encoder.s0,{outChannels:16,kernel:3,stride:1,padding:1}),this.s1b0=new w(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new w(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new w(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new w(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new w(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new w(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new w(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new w(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new w(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new w(t,this.s4b1.output,e.encoder.s4[2],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s5b0=new w(t,this.s4b2.output,e.encoder.s5[0],{inChannels:112,midChannels:672,outChannels:192,kernel:5,stride:2,padding:"same"}),this.s5b1=new w(t,this.s5b0.output,e.encoder.s5[1],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b2=new w(t,this.s5b1.output,e.encoder.s5[2],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b3=new w(t,this.s5b2.output,e.encoder.s5[3],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s6b0=new w(t,this.s5b3.output,e.encoder.s6[0],{inChannels:192,midChannels:1152,outChannels:320,kernel:3,stride:1,padding:1}),this.bottleneck=t.ops.Conv2d(this.s6b0.output,e.bottleneck,{outChannels:128,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new G(t,this.bottleneck.output,this.s4b2.output,e.decoder.blocks[0],{outChannels:64}),this.dec1=new G(t,this.dec0.output,this.s2b1.output,e.decoder.blocks[1],{outChannels:32}),this.dec2=new G(t,this.dec1.output,this.s1b1.output,e.decoder.blocks[2],{outChannels:16}),this.finalUp=t.ops.UpsampleConv1x1(this.dec2.output,e.decoder.finalUpsample,{outH:this.dec2.output.h*2,outW:this.dec2.output.w*2,outChannels:16,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.encoderTaps=[this.s1b1.output,this.s2b1.output,this.s4b2.output,this.s6b0.output],this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run(),this.s1b0.run(),this.s1b1.run(),this.s2b0.run(),this.s2b1.run(),this.s3b0.run(),this.s3b1.run(),this.s3b2.run(),this.s4b0.run(),this.s4b1.run(),this.s4b2.run(),this.s5b0.run(),this.s5b1.run(),this.s5b2.run(),this.s5b3.run(),this.s6b0.run(),this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.dec2.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var wt=[[{in:24,mid:144,out:32,k:3,s:2},{in:32,mid:192,out:32,k:3,s:1},{in:32,mid:192,out:32,k:3,s:1},{in:32,mid:192,out:32,k:3,s:1}],[{in:32,mid:192,out:56,k:5,s:2},{in:56,mid:336,out:56,k:5,s:1},{in:56,mid:336,out:56,k:5,s:1},{in:56,mid:336,out:56,k:5,s:1}],[{in:56,mid:336,out:112,k:3,s:2},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1},{in:112,mid:672,out:112,k:3,s:1}],[{in:112,mid:672,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1},{in:160,mid:960,out:160,k:5,s:1}],[{in:160,mid:960,out:272,k:5,s:2},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1},{in:272,mid:1632,out:272,k:5,s:1}],[{in:272,mid:1632,out:448,k:3,s:1}]],se=class{constructor(t,r,e){a(this,"output");a(this,"featLowRes");a(this,"encoderTaps");a(this,"stem");a(this,"s0");a(this,"stages");a(this,"bottleneck");a(this,"dec0");a(this,"dec1");a(this,"dec2");a(this,"finalUp");a(this,"outConv");a(this,"alpha");this.stem=t.ops.Conv2d(r,e.encoder.stem,{outChannels:32,kernel:3,stride:2,padding:"same",activation:"relu6"}),this.s0=new L(t,this.stem.output,e.encoder.s0,{outChannels:24,kernel:3,stride:1,padding:1});let i=[e.encoder.s1,e.encoder.s2,e.encoder.s3,e.encoder.s4,e.encoder.s5,e.encoder.s6];this.stages=[];let o=this.s0.output;for(let d=0;d<wt.length;d++){let _=[];for(let b=0;b<wt[d].length;b++){let g=wt[d][b],v=new w(t,o,i[d][b],{inChannels:g.in,midChannels:g.mid,outChannels:g.out,kernel:g.k,stride:g.s,padding:g.s===2?"same":(g.k-1)/2});_.push(v),o=v.output}this.stages.push(_)}let n=d=>this.stages[d][this.stages[d].length-1].output,s=n(0),p=n(1),l=n(3),c=n(5);this.bottleneck=t.ops.Conv2d(c,e.bottleneck,{outChannels:256,kernel:1,stride:1,padding:0,activation:"relu6"}),this.dec0=new G(t,this.bottleneck.output,l,e.decoder.blocks[0],{outChannels:128}),this.dec1=new G(t,this.dec0.output,p,e.decoder.blocks[1],{outChannels:64}),this.dec2=new G(t,this.dec1.output,s,e.decoder.blocks[2],{outChannels:32}),this.finalUp=t.ops.UpsampleConv1x1(this.dec2.output,e.decoder.finalUpsample,{outH:this.dec2.output.h*2,outW:this.dec2.output.w*2,outChannels:32,activation:"relu6"}),this.featLowRes=this.finalUp.output,this.encoderTaps=[s,p,l,c],this.outConv=t.ops.Conv2d(this.finalUp.output,e.decoder.outputConv,{outChannels:4,kernel:1,stride:1,padding:0,activation:"none"}),this.alpha=t.ops.UpsampleSigmoid(this.outConv.output,{outH:this.outConv.output.h*2,outW:this.outConv.output.w*2}),this.output=this.alpha.output}run(){this.stem.run(),this.s0.run();for(let t of this.stages)for(let r of t)r.run();this.bottleneck.run(),this.dec0.run(),this.dec1.run(),this.dec2.run(),this.finalUp.run(),this.outConv.run(),this.alpha.run()}};var Bt=ae,Ut=ne,zo=se,O={xs:{base:Bt,wrapper:{variant:"B",cHigh:4,cLow:4,cUp:2},canvasRes:{w:384,h:216},baseRes:{w:128,h:72},flowFuseStem:!0},small:{base:Bt,wrapper:{variant:"A",cHigh:4,cLow:4,cUp:2},canvasRes:{w:384,h:216},baseRes:{w:192,h:108}},medium:{base:Ut,wrapper:{variant:"A",cHigh:4,cLow:4,cUp:2},canvasRes:{w:512,h:288},baseRes:{w:256,h:144}},large:{base:Ut,wrapper:{variant:"D",cHigh:4,cLow:4,cUp:2},canvasRes:{w:640,h:360},baseRes:{w:256,h:144}},xl:{base:zo,wrapper:{variant:"E",cHigh:4,cLow:4,cUp:2},canvasRes:{w:1280,h:720},baseRes:{w:320,h:180}}};var Vo=16,No={tLo:.15,tHi:2.5,leak:.15,release:.9,tDiv:1,divScale:2},$o=15,Xo=5,St=1e3,ue=class{constructor(t){a(this,"canvas");a(this,"backend");a(this,"backendKind");a(this,"topology");a(this,"preset",null);a(this,"enabled");a(this,"currentBackground");a(this,"modelTimingCounter",0);a(this,"renderOp");a(this,"flow",null);a(this,"bgImageInputs",new Map);a(this,"bgVideoInputs",new Map);a(this,"bgVideoPorts",new Map);a(this,"previewCanvas",null);a(this,"previewCtx",null);a(this,"previewBg",null);a(this,"previewEffectSpec",null);a(this,"previewIntervalMs",1e3/$o);a(this,"lastPreviewAt",0);a(this,"skipCounter",0);a(this,"framesRenderedAt",[]);a(this,"modelRunSamples",[]);a(this,"displayRunSamples",[]);a(this,"skippedCount",0);this.backend=t.backend,this.backendKind=t.backendKind,this.canvas=t.canvas,this.enabled=t.enabled,this.currentBackground=t.background,this.topology=t.topology,this.renderOp=new te(this.backend)}process(t){this.renderOp.setSource(t);let r=performance.now(),e=this.renderOp.hasNetwork(),i=this.enabled&&e&&this.currentBackground.kind!=="none",o=this.isPreviewTick(r),n=o&&e&&this.previewBg!==null&&this.previewBg.kind!=="none",s=!1;i&&this.flow?s=this.stepFlow():i&&(this.shouldRunModel()?(this.runModelOnce(),s=!0):this.skippedCount++),!s&&n&&(this.runModelOnce(),s=!0);let p=performance.now();o&&this.previewCanvas?(this.backendKind==="webgl"?this.compositePreviewWebGL(i,n):(this.compositeMain(i),this.renderOp.compositeTo("preview",this.previewSpec(n))),this.lastPreviewAt=r):this.compositeMain(i),this.displayRunSamples.push({ts:performance.now(),ms:performance.now()-p}),this.trimSamples(this.displayRunSamples),this.framesRenderedAt.push(performance.now()),this.trim(this.framesRenderedAt)}compositeMain(t){t?this.renderOp.runDisplay():this.renderOp.runPassthrough()}compositePreviewWebGL(t,r){this.renderOp.refreshDisplayInput(),this.renderOp.compositeTo("preview",this.previewSpec(r));let e=this.canvas.transferToImageBitmap();this.previewCtx.transferFromImageBitmap(e),this.renderOp.compositeMain(!t)}previewSpec(t){return t&&this.previewEffectSpec?this.previewEffectSpec:{mode:"passthrough"}}runModelOnce(){let t=performance.now();this.renderOp.runModel(),this.backendKind==="webgpu"&&this.modelTimingCounter%Xo===0&&this.backend.sync().then(()=>{this.modelRunSamples.push({ts:performance.now(),ms:performance.now()-t}),this.trimSamples(this.modelRunSamples)}).catch(()=>{}),this.modelTimingCounter++}stepFlow(){let t=this.flow,r=!1;return t.networkInput.run(),t.curBaseDown.run(),t.everyFrame?(t.net.run(),t.up.run(),this.runModelOnce(),r=!0,this.backend.copyTensor(t.curBaseDown.output,t.frameAHeld),this.backend.copyTensor(t.tier.output,t.predBuf)):this.shouldRunModel()?(this.runModelOnce(),r=!0,this.backend.copyTensor(t.curBaseDown.output,t.frameAHeld),this.backend.copyTensor(t.tier.output,t.alphaHeld),this.backend.copyTensor(t.tier.output,t.predBuf)):(this.skippedCount++,t.net.run(),t.up.run(),t.predWarp.run(),this.backend.copyTensor(t.predWarp.output,t.predBuf)),t.warm?(t.refWarp.run(),t.stab.run(),this.backend.copyTensor(t.stab.output,t.stabPrev),this.renderOp.applyAlpha(t.stab.output),r):(this.backend.copyTensor(t.tier.output,t.stabPrev),t.warm=r,r)}isPreviewTick(t){return!this.previewCanvas||this.previewBg===null||!this.enabled?!1:t-this.lastPreviewAt>=this.previewIntervalMs}shouldRunModel(){return this.skipCounter===0?(this.skipCounter=this.preset?.skipFrames??0,!0):(this.skipCounter--,!1)}setBackground(t){this.currentBackground=t,this.renderOp.setBackground(this.translateBackgroundFor("main",t))}setEnabled(t){this.enabled=t}attachPreview(t){if(t.width=this.canvas.width,t.height=this.canvas.height,this.previewCanvas=t,this.backendKind==="webgpu")this.backend.attachCanvas("preview",t);else{let r=t.getContext("bitmaprenderer");if(!r)throw new Error("renderer: failed to get bitmaprenderer context for preview canvas");this.previewCtx=r}}setPreview(t,r){this.previewBg=t,this.previewEffectSpec=t.kind==="none"?null:this.translateBackgroundFor("preview",t),r?.fps&&r.fps>0&&(this.previewIntervalMs=1e3/r.fps),this.lastPreviewAt=0}clearPreview(){this.previewBg=null,this.previewEffectSpec=null;let t=this.bgVideoPorts.get("preview");t&&(t.close(),this.bgVideoPorts.delete("preview"))}setPreset(t,r){let e=O[t.model];if(!e)throw new Error(\`renderer: no TIER_CONFIG entry for model '\${t.model}'\`);let i=Wt(r),o=this.backend.ops.Input(e.canvasRes.h,e.canvasRes.w),n=new re(this.backend,o.output,i.base,i.wrapper,e.wrapper,e.base);if(this.renderOp.attachNetwork(n,o,{upscaler:"bilinear",background:this.translateBackgroundFor("main",this.currentBackground)}),this.flow=null,i.flow){let s=e.baseRes,p=e.canvasRes,l=t.skipFrames===0,c=(D,V)=>this.backend.tensor(D,V,4,new Float32Array(D*V*4)),d=this.backend.ops.BilinearUpsample(o.output,{outH:s.h,outW:s.w}),_=c(s.h,s.w),b=new ie(this.backend,_,d.output,n.encoderTaps,i.flow,Vo,e.flowFuseStem?{fuseStem:!0,halfTap:n.halfTap}:{}),g=this.backend.ops.BilinearUpsample(b.output,{outH:p.h,outW:p.w}),v=p.w/s.w,x=c(p.h,p.w),k=c(p.h,p.w),B=this.backend.ops.Warp(k,g.output,{flowScale:v}),U=Math.max(1,Math.round(p.w/b.output.w)),X=Math.max(1,Math.round(p.h/b.output.h)),vt=this.backend.ops.Stabilize(g.output,x,B.output,k,{...No,stepX:U,stepY:X}),z=l?null:c(p.h,p.w),j=z?this.backend.ops.Warp(z,g.output,{flowScale:v}):null;this.flow={tier:n,everyFrame:l,warm:!1,networkInput:o,curBaseDown:d,frameAHeld:_,net:b,up:g,predBuf:x,stabPrev:k,refWarp:B,stab:vt,alphaHeld:z,predWarp:j}}this.preset=t,this.skipCounter=0}destroy(){for(let t of this.bgVideoPorts.values())t.close();this.bgVideoPorts.clear(),this.backend.destroy()}getStats(){let t=performance.now();return this.trimRecent(this.framesRenderedAt,t),this.trimSamplesAt(this.modelRunSamples,t),this.trimSamplesAt(this.displayRunSamples,t),{fps:this.framesRenderedAt.length,modelFps:this.modelRunSamples.length,modelMs:Lt(this.modelRunSamples.map(r=>r.ms)),displayMs:Lt(this.displayRunSamples.map(r=>r.ms)),skipped:this.skippedCount,preset:this.preset?.model??"boot",skipFrames:this.preset?.skipFrames??0,enabled:this.enabled,inputPath:this.topology.input,outputPath:this.topology.output}}translateBackgroundFor(t,r){let e=this.bgVideoPorts.get(t);switch(r.kind!=="video"&&e&&(e.close(),this.bgVideoPorts.delete(t)),r.kind){case"none":return{mode:"solid",color:[0,0,0]};case"color":return{mode:"solid",color:r.rgb};case"blur":return{mode:"blur",sigma:r.sigma};case"image":{let i=this.bgInputFor(this.bgImageInputs,t);return i.setSource(r.bitmap),i.run(),{mode:"image",image:i.output}}case"video":{let i=this.bgInputFor(this.bgVideoInputs,t);return e&&e.close(),this.bgVideoPorts.set(t,r.port),r.port.onmessage=o=>{let n=o.data.frame;try{i.setSource(n),i.run()}finally{n.close()}},r.port.start?.(),{mode:"image",image:i.output}}}}bgInputFor(t,r){let e=t.get(r);return e||(e=this.backend.ops.Input(this.canvas.height,this.canvas.width),t.set(r,e)),e}trim(t){t.length>240&&t.splice(0,t.length-240)}trimSamples(t){t.length>240&&t.splice(0,t.length-240)}trimRecent(t,r){let e=r-St,i=0;for(;i<t.length&&t[i]<e;)i++;i>0&&t.splice(0,i)}trimSamplesAt(t,r){let e=r-St,i=0;for(;i<t.length&&t[i].ts<e;)i++;i>0&&t.splice(0,i)}};function Lt(u){if(u.length===0)return 0;let t=u.slice().sort((e,i)=>e-i),r=t.length>>1;return t.length%2?t[r]:(t[r-1]+t[r])/2}var I=new Float32Array(1),N=new Uint32Array(I.buffer);function jo(u){I[0]=u;let t=N[0],r=t>>>16&32768,e=t&2147483647,i=(e>>>23)-127+15;if((t&2139095040)===2139095040)return(t&8388607)!==0?r|32256:r|31744;if(i>=31)return r|31744;if(i<=0){if(i<-10)return r;let l=e&8388607|8388608,c=14-i,d=l>>>c,_=l>>>c-1&1,b=(l&(1<<c-1)-1)!==0?1:0;return _&&(b||d&1)&&(d+=1),r|d}let o=e>>>13&1023,n=e>>>12&1,s=(e&4095)!==0?1:0,p=i<<10|o;return n&&(s||o&1)&&(p+=1,(p>>>10&31)===31)?r|31744:r|p}function kt(u){let t=(u&32768)<<16,r=(u&31744)>>>10,e=u&1023;if(r===0){if(e===0)return N[0]=t,I[0];let i=e,o=1;for(;(i&1024)===0;)i<<=1,o-=1;return i&=1023,N[0]=t|o+127-15<<23|i<<13,I[0]}return r===31?(N[0]=t|2139095040|e<<13,I[0]):(N[0]=t|r+127-15<<23|e<<13,I[0])}function pe(u){let t=new Uint16Array(u.length);for(let r=0;r<u.length;r++)t[r]=jo(u[r]);return t}function A(u){let t=new Float32Array(u.length);for(let r=0;r<u.length;r++)t[r]=kt(u[r]);return t}var f=class{constructor(t){a(this,"backend",t);a(this,"shader","");a(this,"pipeline");a(this,"bindGroup");a(this,"uniformDefs",[]);a(this,"uniformBuffers",{})}createUniform(t,r){this.uniformDefs.push({name:t,type:r})}setUniform(t,r){let e=this.backend.device.createBuffer({size:r.byteLength,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});r instanceof Uint32Array?new Uint32Array(e.getMappedRange()).set(r):new Float32Array(e.getMappedRange()).set(r),e.unmap(),this.uniformBuffers[t]=e}defaultBindGroup(){let t=[],r=0;for(let e of this.inputs)t.push({binding:r++,resource:{buffer:e.buffer}});for(let e of this.weights)t.push({binding:r++,resource:{buffer:e.buffer}});for(let e of this.uniformDefs)t.push({binding:r++,resource:{buffer:this.uniformBuffers[e.name]}});return t.push({binding:r,resource:{buffer:this.output.buffer}}),this.backend.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:t})}defaultSetup(){let t=this.backend.device.createShaderModule({code:this.shader});this.pipeline=this.backend.device.createComputePipeline({layout:"auto",compute:{module:t,entryPoint:"main"}}),this.bindGroup=this.defaultBindGroup()}run(){let t=this.backend.device.createCommandEncoder(),r=t.beginComputePass();r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.dispatchWorkgroups(...this.dispatch),r.end(),this.backend.device.queue.submit([t.finish()])}};var Ft=\`// Conv2d, output-channel-blocked (K=2) \\u2014 drop-in replacement for conv2d.wgsl.
2
33
  //
3
- // Identical math, layout, and output to conv2d.wgsl, but each thread computes 4
4
- // output channel-groups (16 channels) for one pixel, loading each input vec4
5
- // ONCE and reusing it across all four groups' mat4x4 weight blocks in registers.
6
- // This reuses the *input* operand (re-read once per output group in the baseline)
7
- // and is measurably faster end-to-end on WebGPU across devices. Output is
8
- // bit-identical to conv2d.wgsl (\\u22641 ULP from FMA contraction) \\u2014 MSE tests pass
9
- // unchanged. Dispatch ceil(out_groups / 4) in z (see conv2d.ts).
34
+ // Identical math, layout, and output to conv2d.wgsl, but each thread computes 2
35
+ // output channel-groups (8 channels) for one pixel, loading each input vec4 ONCE
36
+ // and reusing it across both groups' mat4x4 weight blocks in registers. Half the
37
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
38
+ // identical to conv2d.wgsl (\\u22641 ULP from FMA contraction). Dispatch
39
+ // ceil(out_groups / 2) in z (see conv2d.ts).
10
40
  //
11
41
  // Tensor layout: NHWC, channels in vec4 groups (same as conv2d.wgsl).
12
42
  // Weight layout: [K*K][out_groups][in_groups] array of mat4x4 (same as conv2d.wgsl).
@@ -23,7 +53,7 @@ struct Params {
23
53
  stride : u32,
24
54
  pad_top : u32,
25
55
  pad_left : u32,
26
- activation : u32, // 0 = none, 1 = relu6, 2 = relu
56
+ activation : u32, // 0 = none, 1 = relu6, 2 = relu, 3 = leaky
27
57
  }
28
58
 
29
59
  @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
@@ -32,18 +62,19 @@ struct Params {
32
62
  @group(0) @binding(3) var<uniform> params : Params;
33
63
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
34
64
 
35
- const KB = 4u;
65
+ const KB = 2u;
36
66
 
37
67
  fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
38
68
  if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
39
69
  if (a == 2u) { return max(v, vec4<f32>(0.0)); }
70
+ if (a == 3u) { return max(v, 0.1 * v); } // leaky relu (slope 0.1)
40
71
  return v;
41
72
  }
42
73
 
43
74
  @compute @workgroup_size(8, 8, 1)
44
75
  fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
45
- let x = gid.x; // output column
46
- let y = gid.y; // output row
76
+ let x = gid.x; // output column
77
+ let y = gid.y; // output row
47
78
  let o0 = gid.z * KB; // first output channel group
48
79
 
49
80
  if (x >= params.out_w || y >= params.out_h || o0 >= params.out_groups) {
@@ -52,19 +83,13 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
52
83
 
53
84
  let I = params.in_groups;
54
85
  let O = params.out_groups;
55
- // Tail handling when out_groups is not a multiple of 4: clamp the spare lanes
56
- // to o0 (valid index, no OOB) and just don't write them.
86
+ // Tail handling when out_groups is odd: clamp the spare lane to o0 (valid
87
+ // index, no OOB) and just don't write it.
57
88
  let has1 = (o0 + 1u) < O;
58
- let has2 = (o0 + 2u) < O;
59
- let has3 = (o0 + 3u) < O;
60
89
  let o1 = select(o0, o0 + 1u, has1);
61
- let o2 = select(o0, o0 + 2u, has2);
62
- let o3 = select(o0, o0 + 3u, has3);
63
90
 
64
91
  var acc0 = bias_buf[o0];
65
92
  var acc1 = bias_buf[o1];
66
- var acc2 = bias_buf[o2];
67
- var acc3 = bias_buf[o3];
68
93
 
69
94
  for (var ky = 0u; ky < params.kernel_h; ky++) {
70
95
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -80,14 +105,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
80
105
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
81
106
  let wb0 = z * O * I + o0 * I;
82
107
  let wb1 = z * O * I + o1 * I;
83
- let wb2 = z * O * I + o2 * I;
84
- let wb3 = z * O * I + o3 * I;
85
108
  for (var i = 0u; i < I; i++) {
86
- let iv = input_buf[inB + i]; // loaded ONCE, reused across 4 groups
109
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
87
110
  acc0 += weight_buf[wb0 + i] * iv;
88
111
  acc1 += weight_buf[wb1 + i] * iv;
89
- acc2 += weight_buf[wb2 + i] * iv;
90
- acc3 += weight_buf[wb3 + i] * iv;
91
112
  }
92
113
  }
93
114
  }
@@ -95,15 +116,14 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
95
116
  let baseO = y * params.out_w * O + x * O;
96
117
  output_buf[baseO + o0] = act(acc0, params.activation);
97
118
  if (has1) { output_buf[baseO + o1] = act(acc1, params.activation); }
98
- if (has2) { output_buf[baseO + o2] = act(acc2, params.activation); }
99
- if (has3) { output_buf[baseO + o3] = act(acc3, params.activation); }
100
119
  }
101
- \`;var vt=\`enable f16;
120
+ \`;var Et=\`enable f16;
102
121
 
103
- // Conv2d, output-channel-blocked (K=4) \\u2014 full f16. Drop-in replacement for
104
- // conv2d_f16.wgsl. Each thread computes 4 output channel-groups for one pixel,
105
- // loading each input vec4 once and reusing it across all four weight blocks.
106
- // Output is bit-identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 4) in z.
122
+ // Conv2d, output-channel-blocked (K=2) \\u2014 full f16. Drop-in replacement for
123
+ // conv2d_f16.wgsl. Each thread computes 2 output channel-groups for one pixel,
124
+ // loading each input vec4 ONCE and reusing it across both weight blocks. Half the
125
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
126
+ // identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 2) in z.
107
127
 
108
128
  struct Params {
109
129
  in_h : u32,
@@ -126,11 +146,12 @@ struct Params {
126
146
  @group(0) @binding(3) var<uniform> params : Params;
127
147
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
128
148
 
129
- const KB = 4u;
149
+ const KB = 2u;
130
150
 
131
151
  fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
132
152
  if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
133
153
  if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
154
+ if (a == 3u) { return max(v, 0.1h * v); } // leaky relu (slope 0.1)
134
155
  return v;
135
156
  }
136
157
 
@@ -147,16 +168,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
147
168
  let I = params.in_groups;
148
169
  let O = params.out_groups;
149
170
  let has1 = (o0 + 1u) < O;
150
- let has2 = (o0 + 2u) < O;
151
- let has3 = (o0 + 3u) < O;
152
171
  let o1 = select(o0, o0 + 1u, has1);
153
- let o2 = select(o0, o0 + 2u, has2);
154
- let o3 = select(o0, o0 + 3u, has3);
155
172
 
156
173
  var acc0 = bias_buf[o0];
157
174
  var acc1 = bias_buf[o1];
158
- var acc2 = bias_buf[o2];
159
- var acc3 = bias_buf[o3];
160
175
 
161
176
  for (var ky = 0u; ky < params.kernel_h; ky++) {
162
177
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -172,14 +187,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
172
187
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
173
188
  let wb0 = z * O * I + o0 * I;
174
189
  let wb1 = z * O * I + o1 * I;
175
- let wb2 = z * O * I + o2 * I;
176
- let wb3 = z * O * I + o3 * I;
177
190
  for (var i = 0u; i < I; i++) {
178
- let iv = input_buf[inB + i];
191
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
179
192
  acc0 += weight_buf[wb0 + i] * iv;
180
193
  acc1 += weight_buf[wb1 + i] * iv;
181
- acc2 += weight_buf[wb2 + i] * iv;
182
- acc3 += weight_buf[wb3 + i] * iv;
183
194
  }
184
195
  }
185
196
  }
@@ -187,10 +198,156 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
187
198
  let baseO = y * params.out_w * O + x * O;
188
199
  output_buf[baseO + o0] = act(acc0, params.activation);
189
200
  if (has1) { output_buf[baseO + o1] = act(acc1, params.activation); }
190
- if (has2) { output_buf[baseO + o2] = act(acc2, params.activation); }
191
- if (has3) { output_buf[baseO + o3] = act(acc3, params.activation); }
192
201
  }
193
- \`;function w(s,t,r,e){return typeof e=="number"?Math.floor((s+2*e-t)/r)+1:e==="same"?Math.ceil(s/r):Math.floor((s-t)/r)+1}function xo(s,t,r,e){return Math.floor(Math.max((t-1)*e+r-s,0)/2)}function k(s,t,r,e,o){return typeof s=="number"?s:s==="same"?xo(t,r,e,o):0}function d(s){return s instanceof Float32Array||s instanceof Uint16Array?s:new Float32Array(s)}function b(s){let t=Math.max(4,Math.ceil(s.length/4)*4),r=new Float32Array(t);for(let e=0;e<s.length;e++)r[e]=s[e];return r}var oe=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?vt:bt;let n=w(e.h,a.kernel,a.stride,a.padding),u=w(e.w,a.kernel,a.stride,a.padding),p=e.c/4,l=a.outChannels/4,c=k(a.padding,e.h,n,a.kernel,a.stride),m=k(a.padding,e.w,u,a.kernel,a.stride);this.output=r.tensor(n,u,a.outChannels),this.inputs=[e],this.weights=[r.upload(d(o.weights)),r.upload(d(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,u,p,l,a.kernel,a.kernel,a.stride,c,m,a.activation==="relu6"?1:a.activation==="relu"?2:0])),this.defaultSetup(),this.dispatch=[Math.ceil(u/8),Math.ceil(n/8),Math.ceil(l/4)]}};var xt=\`// Depthwise Conv2d \\u2014 groups = in_channels (each channel convolved independently).
202
+ \`;function T(u,t,r,e){return typeof e=="number"?Math.floor((u+2*e-t)/r)+1:e==="same"?Math.ceil(u/r):Math.floor((u-t)/r)+1}function M(u,t,r,e){return(u-1)*r-2*e+t}function Yo(u,t,r,e){return Math.floor(Math.max((t-1)*e+r-u,0)/2)}function C(u,t,r,e,i){return typeof u=="number"?u:u==="same"?Yo(t,r,e,i):0}function m(u){return u instanceof Float32Array||u instanceof Uint16Array?u:new Float32Array(u)}function y(u){let t=Math.max(4,Math.ceil(u.length/4)*4),r=new Float32Array(t),e=u instanceof Uint16Array;for(let i=0;i<u.length;i++)r[i]=e?kt(u[i]):u[i];return r}var le=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Et:Ft;let n=T(e.h,o.kernel,o.stride,o.padding),s=T(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=o.outChannels/4,c=C(o.padding,e.h,n,o.kernel,o.stride),d=C(o.padding,e.w,s,o.kernel,o.stride);this.output=r.tensor(n,s,o.outChannels),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(m(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,s,p,l,o.kernel,o.kernel,o.stride,c,d,o.activation==="relu6"?1:o.activation==="relu"?2:o.activation==="leaky"?3:0])),this.defaultSetup(),this.dispatch=[Math.ceil(s/8),Math.ceil(n/8),Math.ceil(l/2)]}};var Dt=\`// ConvTranspose2d \\u2014 gather form, f32 variant. See conv_transpose2d_f16.wgsl for
203
+ // the math; this is the f32 storage build (mat4x4<f32>).
204
+
205
+ struct Params {
206
+ in_h : u32,
207
+ in_w : u32,
208
+ out_h : u32,
209
+ out_w : u32,
210
+ in_groups : u32,
211
+ out_groups : u32,
212
+ kernel_h : u32,
213
+ kernel_w : u32,
214
+ stride : u32,
215
+ pad_top : u32,
216
+ pad_left : u32,
217
+ activation : u32,
218
+ }
219
+
220
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
221
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f32>>;
222
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f32>>;
223
+ @group(0) @binding(3) var<uniform> params : Params;
224
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
225
+
226
+ fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
227
+ if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
228
+ if (a == 2u) { return max(v, vec4<f32>(0.0)); }
229
+ if (a == 3u) { return max(v, 0.1 * v); }
230
+ return v;
231
+ }
232
+
233
+ @compute @workgroup_size(8, 8, 1)
234
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
235
+ let ox = gid.x;
236
+ let oy = gid.y;
237
+ let o = gid.z;
238
+
239
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
240
+ return;
241
+ }
242
+
243
+ let I = params.in_groups;
244
+ let O = params.out_groups;
245
+ let s = i32(params.stride);
246
+
247
+ var result = bias_buf[o];
248
+
249
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
250
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
251
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
252
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
253
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
254
+ continue;
255
+ }
256
+ let iy = iy_num / s;
257
+ let ix = ix_num / s;
258
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
259
+ continue;
260
+ }
261
+
262
+ let z = ky * params.kernel_w + kx;
263
+ for (var i = 0u; i < I; i++) {
264
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
265
+ let w_idx = z * O * I + o * I + i;
266
+ result += weight_buf[w_idx] * input_buf[in_idx];
267
+ }
268
+ }
269
+ }
270
+
271
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
272
+ }
273
+ \`;var Ot=\`enable f16;
274
+
275
+ // ConvTranspose2d \\u2014 gather form, full f16 variant.
276
+ // Each output (oy,ox) sums every input pixel + kernel tap that maps onto it:
277
+ // iy = (oy + pad - ky) / stride (must divide evenly and be in bounds)
278
+ // No explicit kernel flip \\u2014 the (oy + pad - ky) indexing carries it.
279
+ // Weight layout is IDENTICAL to conv2d (mat4x4[z][o][i], M[in_sub][out_sub] =
280
+ // W(in, out, ky, kx)), so the op uploads the flat buffer unchanged.
281
+
282
+ struct Params {
283
+ in_h : u32,
284
+ in_w : u32,
285
+ out_h : u32,
286
+ out_w : u32,
287
+ in_groups : u32,
288
+ out_groups : u32,
289
+ kernel_h : u32,
290
+ kernel_w : u32,
291
+ stride : u32,
292
+ pad_top : u32,
293
+ pad_left : u32,
294
+ activation : u32,
295
+ }
296
+
297
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
298
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f16>>;
299
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f16>>;
300
+ @group(0) @binding(3) var<uniform> params : Params;
301
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
302
+
303
+ fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
304
+ if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
305
+ if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
306
+ if (a == 3u) { return max(v, 0.1h * v); }
307
+ return v;
308
+ }
309
+
310
+ @compute @workgroup_size(8, 8, 1)
311
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
312
+ let ox = gid.x;
313
+ let oy = gid.y;
314
+ let o = gid.z;
315
+
316
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
317
+ return;
318
+ }
319
+
320
+ let I = params.in_groups;
321
+ let O = params.out_groups;
322
+ let s = i32(params.stride);
323
+
324
+ var result = bias_buf[o];
325
+
326
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
327
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
328
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
329
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
330
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
331
+ continue;
332
+ }
333
+ let iy = iy_num / s;
334
+ let ix = ix_num / s;
335
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
336
+ continue;
337
+ }
338
+
339
+ let z = ky * params.kernel_w + kx;
340
+ for (var i = 0u; i < I; i++) {
341
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
342
+ let w_idx = z * O * I + o * I + i;
343
+ result += weight_buf[w_idx] * input_buf[in_idx];
344
+ }
345
+ }
346
+ }
347
+
348
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
349
+ }
350
+ \`;var ce=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Ot:Dt;let n=M(e.h,o.kernel,o.stride,o.padding),s=M(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=o.outChannels/4;this.output=r.tensor(n,s,o.outChannels),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(m(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,s,p,l,o.kernel,o.kernel,o.stride,o.padding,o.padding,o.activation==="relu6"?1:o.activation==="relu"?2:o.activation==="leaky"?3:0])),this.defaultSetup(),this.dispatch=[Math.ceil(s/8),Math.ceil(n/8),l]}};var It=\`// Depthwise Conv2d \\u2014 groups = in_channels (each channel convolved independently).
194
351
  //
195
352
  // Weight layout: [K*K][channel_groups] array of vec4
196
353
  // weight index = (ky*kernel_w + kx) * channel_groups + c
@@ -265,7 +422,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
265
422
  let out_idx = y * params.out_w * C + x * C + c;
266
423
  output_buf[out_idx] = result;
267
424
  }
268
- \`;var yt=\`enable f16;
425
+ \`;var At=\`enable f16;
269
426
 
270
427
  // Depthwise conv2d \\u2014 full f16 variant. All buffers f16.
271
428
 
@@ -330,7 +487,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
330
487
 
331
488
  output_buf[y * params.out_w * C + x * C + c] = result;
332
489
  }
333
- \`;var ie=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?yt:xt;let n=w(e.h,a.kernel,a.stride,a.padding),u=w(e.w,a.kernel,a.stride,a.padding),p=e.c/4,l=k(a.padding,e.h,n,a.kernel,a.stride),c=k(a.padding,e.w,u,a.kernel,a.stride);this.output=r.tensor(n,u,e.c),this.inputs=[e],this.weights=[r.upload(d(o.weights)),r.upload(d(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,u,p,a.kernel,a.kernel,a.stride,l,c,a.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(u/8),Math.ceil(n/8),p]}};var wt=\`// Element-wise add of two tensors \\u2014 used for residual connections in MBConv blocks.
490
+ \`;var de=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?At:It;let n=T(e.h,o.kernel,o.stride,o.padding),s=T(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=C(o.padding,e.h,n,o.kernel,o.stride),c=C(o.padding,e.w,s,o.kernel,o.stride);this.output=r.tensor(n,s,e.c),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(m(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,s,p,o.kernel,o.kernel,o.stride,l,c,o.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(s/8),Math.ceil(n/8),p]}};var Mt=\`// Element-wise add of two tensors \\u2014 used for residual connections in MBConv blocks.
334
491
  // Operates on the flat float buffer directly; layout is irrelevant for a pure element-wise op.
335
492
 
336
493
  struct Params {
@@ -351,7 +508,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
351
508
  if (idx >= params.size) { return; }
352
509
  output[idx] = input_a[idx] + input_b[idx];
353
510
  }
354
- \`;var kt=\`enable f16;
511
+ \`;var Rt=\`enable f16;
355
512
 
356
513
  // Element-wise add \\u2014 full f16 variant.
357
514
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -374,7 +531,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
374
531
  if (idx >= params.size) { return; }
375
532
  output[idx] = input_a[idx] + input_b[idx];
376
533
  }
377
- \`;var ae=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?kt:wt;let a=e.h*e.w*e.c;this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e,o],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([a,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(a/256),1,1]}};var Tt=\`// Element-wise sigmoid: output = 1 / (1 + exp(-x)).
534
+ \`;var me=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Rt:Mt;let o=e.h*e.w*e.c;this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e,i],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/256),1,1]}};var Ht=\`// Element-wise sigmoid: output = 1 / (1 + exp(-x)).
378
535
  // Operates on packed vec4 buffers (NHWC layout). exp() and arithmetic are element-wise on vec4.
379
536
 
380
537
  struct Params {
@@ -394,7 +551,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
394
551
  if (idx >= params.n_groups) { return; }
395
552
  output_buf[idx] = 1.0 / (1.0 + exp(-input_buf[idx]));
396
553
  }
397
- \`;var Ct=\`enable f16;
554
+ \`;var zt=\`enable f16;
398
555
 
399
556
  // Sigmoid \\u2014 full f16 variant.
400
557
 
@@ -416,7 +573,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
416
573
  let x = vec4<f32>(input_buf[idx]);
417
574
  output_buf[idx] = vec4<f16>(1.0 / (1.0 + exp(-x)));
418
575
  }
419
- \`;var ne=class extends f{constructor(r,e){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Ct:Tt;let o=e.h*e.w*(e.c/4);this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/256),1,1]}};var Wt=\`// Element-wise tanh \\u2014 used by ConvGRU candidate activation.
576
+ \`;var fe=class extends f{constructor(r,e){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?zt:Ht;let i=e.h*e.w*(e.c/4);this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([i,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(i/256),1,1]}};var Vt=\`// Element-wise tanh \\u2014 used by ConvGRU candidate activation.
420
577
  // Operates on packed vec4 buffers (NHWC layout). tanh() is element-wise on vec4.
421
578
 
422
579
  struct Params {
@@ -436,7 +593,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
436
593
  if (idx >= params.n_groups) { return; }
437
594
  output_buf[idx] = tanh(input_buf[idx]);
438
595
  }
439
- \`;var Pt=\`enable f16;
596
+ \`;var Nt=\`enable f16;
440
597
 
441
598
  // Tanh \\u2014 full f16 variant.
442
599
 
@@ -458,7 +615,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
458
615
  let x = vec4<f32>(input_buf[idx]);
459
616
  output_buf[idx] = vec4<f16>(tanh(x));
460
617
  }
461
- \`;var se=class extends f{constructor(r,e){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Pt:Wt;let o=e.h*e.w*(e.c/4);this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/256),1,1]}};var Gt=\`// Element-wise multiply \\u2014 used in ConvGRU for r \\u2299 h_prev.
618
+ \`;var he=class extends f{constructor(r,e){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Nt:Vt;let i=e.h*e.w*(e.c/4);this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([i,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(i/256),1,1]}};var $t=\`// Element-wise multiply \\u2014 used in ConvGRU for r \\u2299 h_prev.
462
619
  // Same flat-float layout as add.wgsl.
463
620
 
464
621
  struct Params {
@@ -479,7 +636,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
479
636
  if (idx >= params.size) { return; }
480
637
  output[idx] = input_a[idx] * input_b[idx];
481
638
  }
482
- \`;var Bt=\`enable f16;
639
+ \`;var Xt=\`enable f16;
483
640
 
484
641
  // Element-wise multiply \\u2014 full f16 variant.
485
642
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -502,7 +659,208 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
502
659
  if (idx >= params.size) { return; }
503
660
  output[idx] = input_a[idx] * input_b[idx];
504
661
  }
505
- \`;var ue=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Bt:Gt;let a=e.h*e.w*e.c;this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e,o],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([a,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(a/256),1,1]}};var Ut=\`// Bilinear upsample (arbitrary ratio), align_corners=False (matches PyTorch default).
662
+ \`;var _e=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Xt:$t;let o=e.h*e.w*e.c;this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e,i],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/256),1,1]}};var jt=\`// Bilinear gather-warp (f32). See warp_f16.wgsl for the math.
663
+
664
+ struct Params {
665
+ h : u32,
666
+ w : u32,
667
+ flow_scale : f32,
668
+ }
669
+
670
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f32>>;
671
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f32>>;
672
+ @group(0) @binding(2) var<uniform> params : Params;
673
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f32>>;
674
+
675
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
676
+ let cx = clamp(x, 0, W - 1);
677
+ let cy = clamp(y, 0, H - 1);
678
+ return source_buf[u32(cy) * u32(W) + u32(cx)];
679
+ }
680
+
681
+ @compute @workgroup_size(8, 8, 1)
682
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
683
+ let x = gid.x;
684
+ let y = gid.y;
685
+ if (x >= params.w || y >= params.h) { return; }
686
+
687
+ let W = i32(params.w);
688
+ let H = i32(params.h);
689
+ let idx = y * params.w + x;
690
+
691
+ let f = flow_buf[idx].xy;
692
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
693
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
694
+
695
+ let x0 = i32(floor(sx));
696
+ let y0 = i32(floor(sy));
697
+ let tx = sx - f32(x0);
698
+ let ty = sy - f32(y0);
699
+
700
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
701
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
702
+ output_buf[idx] = mix(top, bot, ty);
703
+ }
704
+ \`;var qt=\`enable f16;
705
+
706
+ // Bilinear gather-warp (f16 storage, f32 coordinate math). For each output pixel
707
+ // p, sample the source at p + flow_scale\\xB7flow[p].xy and bilinearly interpolate,
708
+ // clamping the sample to the edge (border-replicate). Source + flow are 4-ch
709
+ // (1 group), same resolution; flow vector is in .xy.
710
+
711
+ struct Params {
712
+ h : u32,
713
+ w : u32,
714
+ flow_scale : f32,
715
+ }
716
+
717
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f16>>;
718
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f16>>;
719
+ @group(0) @binding(2) var<uniform> params : Params;
720
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f16>>;
721
+
722
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
723
+ let cx = clamp(x, 0, W - 1);
724
+ let cy = clamp(y, 0, H - 1);
725
+ return vec4<f32>(source_buf[u32(cy) * u32(W) + u32(cx)]);
726
+ }
727
+
728
+ @compute @workgroup_size(8, 8, 1)
729
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
730
+ let x = gid.x;
731
+ let y = gid.y;
732
+ if (x >= params.w || y >= params.h) { return; }
733
+
734
+ let W = i32(params.w);
735
+ let H = i32(params.h);
736
+ let idx = y * params.w + x;
737
+
738
+ let f = vec2<f32>(flow_buf[idx].xy);
739
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
740
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
741
+
742
+ let x0 = i32(floor(sx));
743
+ let y0 = i32(floor(sy));
744
+ let tx = sx - f32(x0);
745
+ let ty = sy - f32(y0);
746
+
747
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
748
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
749
+ output_buf[idx] = vec4<f16>(mix(top, bot, ty));
750
+ }
751
+ \`;var ge=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?qt:jt,this.output=r.tensor(e.h,e.w,e.c),this.inputs=[e,i],this.createUniform("params","Params");let n=new Uint32Array(3);n[0]=e.h,n[1]=e.w,new Float32Array(n.buffer)[2]=o.flowScale,this.setUniform("params",n),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Kt=\`// Flow-gated temporal stabilizer (f32). See stabilize_f16.wgsl for the math.
752
+
753
+ struct Params {
754
+ h : u32,
755
+ w : u32,
756
+ t_lo : f32,
757
+ t_hi : f32,
758
+ leak : f32,
759
+ release : f32,
760
+ t_div : f32,
761
+ div_scale: f32,
762
+ step_x : u32,
763
+ step_y : u32,
764
+ }
765
+
766
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f32>>;
767
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f32>>;
768
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f32>>;
769
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f32>>;
770
+ @group(0) @binding(4) var<uniform> params : Params;
771
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f32>>;
772
+
773
+ @compute @workgroup_size(8, 8, 1)
774
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
775
+ let x = gid.x;
776
+ let y = gid.y;
777
+ if (x >= params.w || y >= params.h) { return; }
778
+ let idx = y * params.w + x;
779
+
780
+ let mag = length(flow_buf[idx].xy);
781
+ let env_prev = env_prev_buf[idx].y;
782
+ let env = max(mag, params.release * env_prev);
783
+
784
+ let xr = min(x + params.step_x, params.w - 1u);
785
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
786
+ let yd = min(y + params.step_y, params.h - 1u);
787
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
788
+ let dfx = flow_buf[y * params.w + xr].x - flow_buf[y * params.w + xl].x;
789
+ let dfy = flow_buf[yd * params.w + x].y - flow_buf[yu * params.w + x].y;
790
+ let divg = abs(dfx + dfy);
791
+
792
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
793
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
794
+ let g = max(max(g_mag, g_div), params.leak);
795
+
796
+ let pred = pred_buf[idx].x;
797
+ let refv = ref_buf[idx].x;
798
+ let stab = g * pred + (1.0 - g) * refv;
799
+
800
+ output_buf[idx] = vec4<f32>(stab, env, 0.0, 0.0);
801
+ }
802
+ \`;var Yt=\`enable f16;
803
+
804
+ // Flow-gated temporal stabilizer (f16 storage, f32 gate math). Per pixel:
805
+ // env = max(|flow.xy|, release\\xB7envPrev.y) peak-hold (fast attack, slow release)
806
+ // div = |\\u2202fx/\\u2202x + \\u2202fy/\\u2202y| flow divergence (occlusion seam)
807
+ // g = max(clamp((env-tLo)/(tHi-tLo),0,1), clamp((div-tDiv)/divScale,0,1), leak)
808
+ // out = vec4((g\\xB7pred + (1-g)\\xB7ref).x, env, 0, 0)
809
+ // The divergence term opens the gate at occlusion/disocclusion boundaries (where
810
+ // the flow tears but the revealed-background magnitude is ~0). Finite-difference
811
+ // step spans ~1 base/4 pixel. alpha is in .x of pred/ref; env threads via .y.
812
+
813
+ struct Params {
814
+ h : u32,
815
+ w : u32,
816
+ t_lo : f32,
817
+ t_hi : f32,
818
+ leak : f32,
819
+ release : f32,
820
+ t_div : f32,
821
+ div_scale: f32,
822
+ step_x : u32,
823
+ step_y : u32,
824
+ }
825
+
826
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f16>>;
827
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f16>>;
828
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f16>>;
829
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f16>>;
830
+ @group(0) @binding(4) var<uniform> params : Params;
831
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f16>>;
832
+
833
+ @compute @workgroup_size(8, 8, 1)
834
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
835
+ let x = gid.x;
836
+ let y = gid.y;
837
+ if (x >= params.w || y >= params.h) { return; }
838
+ let idx = y * params.w + x;
839
+
840
+ let mag = length(vec2<f32>(flow_buf[idx].xy));
841
+ let env_prev = f32(env_prev_buf[idx].y);
842
+ let env = max(mag, params.release * env_prev);
843
+
844
+ // Flow divergence over a \\xB1step finite-difference (clamped to the edges).
845
+ let xr = min(x + params.step_x, params.w - 1u);
846
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
847
+ let yd = min(y + params.step_y, params.h - 1u);
848
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
849
+ let dfx = f32(flow_buf[y * params.w + xr].x) - f32(flow_buf[y * params.w + xl].x);
850
+ let dfy = f32(flow_buf[yd * params.w + x].y) - f32(flow_buf[yu * params.w + x].y);
851
+ let divg = abs(dfx + dfy);
852
+
853
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
854
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
855
+ let g = max(max(g_mag, g_div), params.leak);
856
+
857
+ let pred = f32(pred_buf[idx].x);
858
+ let refv = f32(ref_buf[idx].x);
859
+ let stab = g * pred + (1.0 - g) * refv;
860
+
861
+ output_buf[idx] = vec4<f16>(f16(stab), f16(env), 0.0h, 0.0h);
862
+ }
863
+ \`;var be=class extends f{constructor(r,e,i,o,n,s){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Yt:Kt,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i,o,n],this.createUniform("params","Params");let p=new Uint32Array(10);p[0]=e.h,p[1]=e.w;let l=new Float32Array(p.buffer);l[2]=s.tLo,l[3]=s.tHi,l[4]=s.leak,l[5]=s.release,l[6]=s.tDiv,l[7]=s.divScale,p[8]=s.stepX,p[9]=s.stepY,this.setUniform("params",p),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Qt=\`// Bilinear upsample (arbitrary ratio), align_corners=False (matches PyTorch default).
506
864
  // Input/output in NHWC vec4 format: index = y*W*(C/4) + x*(C/4) + c_group.
507
865
  // Each thread computes one output pixel for one channel group (vec4 = 4 channels).
508
866
 
@@ -560,7 +918,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
560
918
 
561
919
  output_buf[oy * params.out_w * C + ox * C + c] = result;
562
920
  }
563
- \`;var St=\`enable f16;
921
+ \`;var Jt=\`enable f16;
564
922
 
565
923
  // Bilinear upsample 2\\xD7 \\u2014 full f16 variant.
566
924
  // Interpolation weights (wx, wy) and intermediate blends computed in f32 for
@@ -616,7 +974,53 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
616
974
 
617
975
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(result);
618
976
  }
619
- \`;var pe=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?St:Ut;let a=e.c/4;this.output=r.tensor(o.outH,o.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o.outH,o.outW,a,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o.outW/8),Math.ceil(o.outH/8),a]}};var Lt=\`// Bicubic upsample (arbitrary scale) \\u2014 Keys cubic, a=-0.75 (PyTorch default
977
+ \`;var ve=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Jt:Qt;let o=e.c/4;this.output=r.tensor(i.outH,i.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i.outH,i.outW,o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(i.outW/8),Math.ceil(i.outH/8),o]}};var Zt=\`// Top-left crop (f32). See crop_f16.wgsl.
978
+
979
+ struct Params {
980
+ in_w : u32,
981
+ out_h : u32,
982
+ out_w : u32,
983
+ groups : u32,
984
+ }
985
+
986
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
987
+ @group(0) @binding(1) var<uniform> params : Params;
988
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f32>>;
989
+
990
+ @compute @workgroup_size(8, 8, 1)
991
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
992
+ let x = gid.x;
993
+ let y = gid.y;
994
+ let g = gid.z;
995
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
996
+ let G = params.groups;
997
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
998
+ }
999
+ \`;var er=\`enable f16;
1000
+
1001
+ // Top-left crop: output[y,x,g] = input[y,x,g] for y<outH, x<outW (training crop_like).
1002
+
1003
+ struct Params {
1004
+ in_w : u32,
1005
+ out_h : u32,
1006
+ out_w : u32,
1007
+ groups : u32,
1008
+ }
1009
+
1010
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
1011
+ @group(0) @binding(1) var<uniform> params : Params;
1012
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f16>>;
1013
+
1014
+ @compute @workgroup_size(8, 8, 1)
1015
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1016
+ let x = gid.x;
1017
+ let y = gid.y;
1018
+ let g = gid.z;
1019
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
1020
+ let G = params.groups;
1021
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
1022
+ }
1023
+ \`;var xe=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?er:Zt;let o=e.c/4;this.output=r.tensor(i.outH,i.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.w,i.outH,i.outW,o])),this.defaultSetup(),this.dispatch=[Math.ceil(i.outW/8),Math.ceil(i.outH/8),o]}};var tr=\`// Bicubic upsample (arbitrary scale) \\u2014 Keys cubic, a=-0.75 (PyTorch default
620
1024
  // for mode='bicubic', align_corners=False). Direct 2D, 4\\xD74 = 16 taps per
621
1025
  // output pixel. NHWC vec4 layout: index = y*W*(C/4) + x*(C/4) + c_group.
622
1026
 
@@ -683,7 +1087,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
683
1087
 
684
1088
  output_buf[oy * params.out_w * C + ox * C + c] = acc;
685
1089
  }
686
- \`;var Ft=\`enable f16;
1090
+ \`;var rr=\`enable f16;
687
1091
 
688
1092
  // Bicubic upsample \\u2014 full f16 storage variant. Bicubic weights and the per-
689
1093
  // pixel accumulator are computed in f32 (cheap to keep precision around the
@@ -752,7 +1156,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
752
1156
 
753
1157
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(acc);
754
1158
  }
755
- \`;var le=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Ft:Lt;let a=e.c/4;this.output=r.tensor(o.outH,o.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o.outH,o.outW,a,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o.outW/8),Math.ceil(o.outH/8),a]}};var Et=\`// Channel concatenation: output = cat(A, B, dim=channel).
1159
+ \`;var ye=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?rr:tr;let o=e.c/4;this.output=r.tensor(i.outH,i.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i.outH,i.outW,o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(i.outW/8),Math.ceil(i.outH/8),o]}};var or=\`// Channel concatenation: output = cat(A, B, dim=channel).
756
1160
  // Both A and B must share the same H\\xD7W and be in NHWC vec4 format.
757
1161
  // Output layout: for each (y, x), the first a_groups vec4s come from A,
758
1162
  // followed by b_groups vec4s from B.
@@ -797,7 +1201,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
797
1201
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
798
1202
  }
799
1203
  }
800
- \`;var Ot=\`enable f16;
1204
+ \`;var ir=\`enable f16;
801
1205
 
802
1206
  // Channel concatenation \\u2014 full f16 variant.
803
1207
 
@@ -838,7 +1242,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
838
1242
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
839
1243
  }
840
1244
  }
841
- \`;var ce=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Ot:Et;let a=e.c/4,n=o.c/4,u=a+n;this.output=r.tensor(e.h,e.w,e.c+o.c),this.inputs=[e,o],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,a,n,u,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),u]}};var It=\`// Conv2d + skip add fused.
1245
+ \`;var we=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?ir:or;let o=e.c/4,n=i.c/4,s=o+n;this.output=r.tensor(e.h,e.w,e.c+i.c),this.inputs=[e,i],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,n,s,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),s]}};var ar=\`// Conv2d + skip add fused.
842
1246
  // Identical to conv2d.wgsl except skip is an activation input (binding 1),
843
1247
  // added element-wise to the conv result at write time.
844
1248
  // Eliminates the separate add dispatch and its intermediate buffer round-trip.
@@ -912,7 +1316,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
912
1316
  let out_idx = y * params.out_w * O + x * O + o;
913
1317
  output_buf[out_idx] = result + skip_buf[out_idx];
914
1318
  }
915
- \`;var Dt=\`enable f16;
1319
+ \`;var nr=\`enable f16;
916
1320
 
917
1321
  // Conv2d + skip add fused \\u2014 full f16 variant.
918
1322
 
@@ -986,7 +1390,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
986
1390
  let out_idx = y * params.out_w * O + x * O + o;
987
1391
  output_buf[out_idx] = result + skip_buf[out_idx];
988
1392
  }
989
- \`;var de=class extends f{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Dt:It;let u=w(e.h,n.kernel,n.stride,n.padding),p=w(e.w,n.kernel,n.stride,n.padding),l=e.c/4,c=n.outChannels/4,m=k(n.padding,e.h,u,n.kernel,n.stride),_=k(n.padding,e.w,p,n.kernel,n.stride);this.output=r.tensor(u,p,n.outChannels),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(d(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,u,p,l,c,n.kernel,n.kernel,n.stride,m,_,n.activation==="relu6"?1:0])),this.defaultSetup(),this.dispatch=[Math.ceil(p/8),Math.ceil(u/8),c]}};var At=\`// proj_residual: bespoke 1\\xD71 conv (no activation) + residual add, fused.
1393
+ \`;var ke=class extends f{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?nr:ar;let s=T(e.h,n.kernel,n.stride,n.padding),p=T(e.w,n.kernel,n.stride,n.padding),l=e.c/4,c=n.outChannels/4,d=C(n.padding,e.h,s,n.kernel,n.stride),_=C(n.padding,e.w,p,n.kernel,n.stride);this.output=r.tensor(s,p,n.outChannels),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(m(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,s,p,l,c,n.kernel,n.kernel,n.stride,d,_,n.activation==="relu6"?1:0])),this.defaultSetup(),this.dispatch=[Math.ceil(p/8),Math.ceil(s/8),c]}};var sr=\`// proj_residual: bespoke 1\\xD71 conv (no activation) + residual add, fused.
990
1394
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation: drops
991
1395
  // the kernel loop, the padding checks, and the activation branch. Used by the
992
1396
  // MBConv project+residual tail. Both inputs share the same spatial resolution.
@@ -1031,7 +1435,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1031
1435
 
1032
1436
  output_buf[pix * O + o] = result;
1033
1437
  }
1034
- \`;var Rt=\`enable f16;
1438
+ \`;var ur=\`enable f16;
1035
1439
 
1036
1440
  // proj_residual \\u2014 full f16 variant. See proj_residual.wgsl for layout details.
1037
1441
  // Bespoke 1\\xD71 conv (no activation) + residual add, fused.
@@ -1073,7 +1477,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1073
1477
 
1074
1478
  output_buf[pix * O + o] = result;
1075
1479
  }
1076
- \`;var me=class extends f{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Rt:At;let u=e.c/4,p=n.outChannels/4;this.output=r.tensor(e.h,e.w,n.outChannels),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(d(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,u,p])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),p]}};var Mt=\`// concat_conv2d: fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one
1480
+ \`;var Te=class extends f{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?ur:sr;let s=e.c/4,p=n.outChannels/4;this.output=r.tensor(e.h,e.w,n.outChannels),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(m(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,s,p])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),p]}};var pr=\`// concat_conv2d: fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one
1077
1481
  // dispatch. Both inputs are already at the output resolution (the upstream
1078
1482
  // upsample stays a separate dispatch writing a clean intermediate, so the conv
1079
1483
  // reads are plain-indexed). Identical math to conv2d; the only difference is
@@ -1133,7 +1537,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1133
1537
  result = clamp(result, vec4<f32>(0.0), vec4<f32>(6.0));
1134
1538
  output_buf[(y * p.w + x) * O + o] = result;
1135
1539
  }
1136
- \`;var Ht=\`enable f16;
1540
+ \`;var lr=\`enable f16;
1137
1541
 
1138
1542
  // concat_conv2d \\u2014 full f16 variant. See concat_conv2d.wgsl for layout details.
1139
1543
  // Fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one dispatch.
@@ -1188,7 +1592,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1188
1592
  result = clamp(result, vec4<f16>(0.0h), vec4<f16>(6.0h));
1189
1593
  output_buf[(y * p.w + x) * O + o] = result;
1190
1594
  }
1191
- \`;var fe=class extends f{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Ht:Mt;let u=e.c/4,p=o.c/4,l=n.outChannels/4;this.output=r.tensor(e.h,e.w,n.outChannels),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(d(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,u,p,l,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),l]}};var zt=\`// gates_fused: ConvGRU z + r gates, fused into one dispatch.
1595
+ \`;var Ce=class extends f{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?lr:pr;let s=e.c/4,p=i.c/4,l=n.outChannels/4;this.output=r.tensor(e.h,e.w,n.outChannels),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(m(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,s,p,l,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),l]}};var cr=\`// gates_fused: ConvGRU z + r gates, fused into one dispatch.
1192
1596
  // Production config (c_up=2, split_ratio=0.5 \\u2192 passthrough=1, recurrent=1):
1193
1597
  // u_in : c_up=2 packed in a vec4 (.x = passthrough a, .y = recurrent b)
1194
1598
  // h_prev : hidden carrier \\u2014 recurrent state in .z (see cand_update_fused: the
@@ -1233,7 +1637,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1233
1637
  let r = 1.0 / (1.0 + exp(-r_pre));
1234
1638
  output_buf[y * params.w + x] = vec4<f32>(z, r, 0.0, 0.0);
1235
1639
  }
1236
- \`;var Vt=\`enable f16;
1640
+ \`;var dr=\`enable f16;
1237
1641
 
1238
1642
  // gates_fused \\u2014 full f16 variant. See gates_fused.wgsl for layout details.
1239
1643
  // ConvGRU z + r gates (production config c_up=2, recurrent=1).
@@ -1275,7 +1679,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1275
1679
  let r = 1.0h / (1.0h + exp(-r_pre));
1276
1680
  output_buf[y * params.w + x] = vec4<f16>(z, r, 0.0h, 0.0h);
1277
1681
  }
1278
- \`;var he=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Vt:zt,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(b(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Nt=\`// cand_update_fused: ConvGRU candidate path + state update + output, fused.
1682
+ \`;var We=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?dr:cr,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(y(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var mr=\`// cand_update_fused: ConvGRU candidate path + state update + output, fused.
1279
1683
  // Production config (c_up=2, recurrent=1):
1280
1684
  // u_in : c_up=2 (.x = a passthrough, .y = b recurrent)
1281
1685
  // h_prev : hidden carrier \\u2014 recurrent state in .z (the previous frame's
@@ -1328,7 +1732,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1328
1732
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
1329
1733
  output_buf[cur] = vec4<f32>(u_cur.x, b_out, h_new, 0.0);
1330
1734
  }
1331
- \`;var $t=\`enable f16;
1735
+ \`;var fr=\`enable f16;
1332
1736
 
1333
1737
  // cand_update_fused \\u2014 full f16 variant. See cand_update_fused.wgsl for details.
1334
1738
  // ConvGRU candidate + state update + output (production config c_up=2, recurrent=1).
@@ -1374,7 +1778,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1374
1778
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
1375
1779
  output_buf[cur] = vec4<f16>(u_cur.x, b_out, h_new, 0.0h);
1376
1780
  }
1377
- \`;var ge=class extends f{constructor(r,e,o,a,n,u){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?$t:Nt,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,o,a],this.weights=[r.upload(d(n.weights)),r.upload(b(n.bias)),r.upload(b(u))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Xt=\`// conv_expand: bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
1781
+ \`;var Pe=class extends f{constructor(r,e,i,o,n,s){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?fr:mr,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i,o],this.weights=[r.upload(m(n.weights)),r.upload(y(n.bias)),r.upload(y(s))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var hr=\`// conv_expand: bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
1378
1782
  // Expands feat_lr (in_c, mult of 4) to the c_up=2 carrier \\u2014 output .xy = the 2
1379
1783
  // native channels, .zw = 0. mat4x2 per (kpos, in_group) with a vec2 accumulator.
1380
1784
  // Weight: 9 * in_groups mat4x2 (8 floats each, col-major). Bias .xy.
@@ -1411,7 +1815,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1411
1815
  result = max(result, vec2<f32>(0.0)); // expand_feat is F.relu
1412
1816
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
1413
1817
  }
1414
- \`;var jt=\`enable f16;
1818
+ \`;var _r=\`enable f16;
1415
1819
 
1416
1820
  // conv_expand \\u2014 full f16 variant. See conv_expand.wgsl for layout details.
1417
1821
  // Bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
@@ -1448,7 +1852,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1448
1852
  result = max(result, vec2<f16>(0.0h));
1449
1853
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
1450
1854
  }
1451
- \`;var _e=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?jt:Xt;let a=e.c/4;this.output=r.tensor(e.h,e.w,4),this.inputs=[e],this.weights=[r.upload(d(o.weights)),r.upload(b(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,a,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var qt=\`// cat_conv_6to2: fused concat(u, d) + 6\\u21922 conv 3\\xD73 (pad 1) + relu (E up1_combine).
1855
+ \`;var Ge=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?_r:hr;let o=e.c/4;this.output=r.tensor(e.h,e.w,4),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(y(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var gr=\`// cat_conv_6to2: fused concat(u, d) + 6\\u21922 conv 3\\xD73 (pad 1) + relu (E up1_combine).
1452
1856
  // u = c_up=2 carrier (.xy); d = c_high=4 (full vec4). Both same resolution.
1453
1857
  // Channel order concat([u, d]) = (u.x, u.y, d.x, d.y, d.z, d.w), split into
1454
1858
  // v3a = (u.x, u.y, d.x) v3b = d.yzw
@@ -1488,7 +1892,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1488
1892
  result = max(result, vec2<f32>(0.0)); // up1_combine is F.relu
1489
1893
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
1490
1894
  }
1491
- \`;var Kt=\`enable f16;
1895
+ \`;var br=\`enable f16;
1492
1896
 
1493
1897
  // cat_conv_6to2 \\u2014 full f16 variant. See cat_conv_6to2.wgsl for layout details.
1494
1898
  // Fused concat(u, d) + 6\\u21922 conv 3\\xD73 (pad 1) + relu (E up1_combine).
@@ -1527,7 +1931,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1527
1931
  result = max(result, vec2<f16>(0.0h));
1528
1932
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
1529
1933
  }
1530
- \`;var be=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Kt:qt,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(b(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Yt=\`// down_adapter: fused stride-N 3\\xD73 conv (4\\u21924) + relu + 1\\xD71 adapter (4\\u21923, no
1934
+ \`;var Be=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?br:gr,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(y(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var vr=\`// down_adapter: fused stride-N 3\\xD73 conv (4\\u21924) + relu + 1\\xD71 adapter (4\\u21923, no
1531
1935
  // act) into one dispatch. E variant: down2 (c_high=4 \\u2192 c_low=4, stride 2) +
1532
1936
  // adapter. A/B variant: down1 (RGB .xyz \\u2192 4, stride 2/3) + adapter (the down
1533
1937
  // weight's 4th input column is zeroed at export for RGB input). Symmetric pad.
@@ -1575,7 +1979,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1575
1979
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
1576
1980
  output_buf[y * p.out_w + x] = vec4<f32>(adapt_out.xyz, 0.0);
1577
1981
  }
1578
- \`;var Qt=\`enable f16;
1982
+ \`;var xr=\`enable f16;
1579
1983
 
1580
1984
  // down_adapter \\u2014 full f16 variant. See down_adapter.wgsl for layout details.
1581
1985
  // Fused stride-N 3\\xD73 conv (4\\u21924) + relu + 1\\xD71 adapter (4\\u21923, no act).
@@ -1620,7 +2024,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1620
2024
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
1621
2025
  output_buf[y * p.out_w + x] = vec4<f16>(adapt_out.xyz, 0.0h);
1622
2026
  }
1623
- \`;var ve=class extends f{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Qt:Yt;let u=w(e.h,3,n.stride,1),p=w(e.w,3,n.stride,1),l=k(1,e.h,u,3,n.stride),c=k(1,e.w,p,3,n.stride);this.output=r.tensor(u,p,4),this.inputs=[e],this.weights=[r.upload(d(o.weights)),r.upload(b(o.bias)),r.upload(d(a.weights)),r.upload(b(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,u,p,n.stride,l,c,0])),this.defaultSetup(),this.dispatch=[Math.ceil(p/8),Math.ceil(u/8),1]}};var Jt=\`// up_final: fused concat(u, rgb) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
2027
+ \`;var Ue=class extends f{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?xr:vr;let s=T(e.h,3,n.stride,1),p=T(e.w,3,n.stride,1),l=C(1,e.h,s,3,n.stride),c=C(1,e.w,p,3,n.stride);this.output=r.tensor(s,p,4),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(y(i.bias)),r.upload(m(o.weights)),r.upload(y(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,s,p,n.stride,l,c,0])),this.defaultSetup(),this.dispatch=[Math.ceil(p/8),Math.ceil(s/8),1]}};var yr=\`// up_final: fused concat(u, rgb) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
1624
2028
  // u = c_up=2 carrier (.xy); rgb = x_hr (.xyz). 5 inputs \\u2192 1 alpha (output .x).
1625
2029
  // Weight: 18 vec4 \\u2014 [0..8] = (w0, w1, 0, 0) for u per kpos; [9..17] =
1626
2030
  // (w2, w3, w4, 0) for rgb per kpos. Bias .x.
@@ -1654,7 +2058,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1654
2058
 
1655
2059
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
1656
2060
  }
1657
- \`;var Zt=\`enable f16;
2061
+ \`;var wr=\`enable f16;
1658
2062
 
1659
2063
  // up_final \\u2014 full f16 variant. See up_final.wgsl for layout details.
1660
2064
  // Fused concat(u, rgb) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
@@ -1688,7 +2092,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1688
2092
 
1689
2093
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
1690
2094
  }
1691
- \`;var xe=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?Zt:Jt,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,o],this.weights=[r.upload(d(a.weights)),r.upload(b(a.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var er=\`// up_final_skip: C/D alpha head. Fused concat(u, d_full, rgb) \\u2192 conv 3\\xD73 9\\u21921
2095
+ \`;var Se=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?wr:yr,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i],this.weights=[r.upload(m(o.weights)),r.upload(y(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var kr=\`// up_final_skip: C/D alpha head. Fused concat(u, d_full, rgb) \\u2192 conv 3\\xD73 9\\u21921
1692
2096
  // \\u2192 sigmoid. u = c_up=2 (.xy); d_full = c_high=4 full-res skip (full vec4);
1693
2097
  // rgb = x_hr (.xyz). Channel order concat = 2 + 4 + 3 = 9. Output .x = alpha.
1694
2098
  // Weight: 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u; [kpos*3+1]=(w2..w5)
@@ -1725,7 +2129,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1725
2129
 
1726
2130
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
1727
2131
  }
1728
- \`;var tr=\`enable f16;
2132
+ \`;var Tr=\`enable f16;
1729
2133
 
1730
2134
  // up_final_skip \\u2014 full f16 variant. See up_final_skip.wgsl for layout details.
1731
2135
  // C/D alpha head: fused concat(u, d_full, rgb) \\u2192 conv 3\\xD73 9\\u21921 \\u2192 sigmoid.
@@ -1761,7 +2165,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1761
2165
 
1762
2166
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
1763
2167
  }
1764
- \`;var ye=class extends f{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?tr:er,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,o,a],this.weights=[r.upload(d(n.weights)),r.upload(b(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var rr=\`// Bilinear upsample + channel concat fused.
2168
+ \`;var Le=class extends f{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Tr:kr,this.output=r.tensor(e.h,e.w,4),this.inputs=[e,i,o],this.weights=[r.upload(m(n.weights)),r.upload(y(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1]}};var Cr=\`// Bilinear upsample + channel concat fused.
1765
2169
  // input_a is the decoder tensor at small spatial resolution (in_h \\xD7 in_w).
1766
2170
  // input_b is the encoder skip feature already at output resolution (out_h \\xD7 out_w).
1767
2171
  // For output channels 0..a_groups-1: bilinearly interpolate from input_a.
@@ -1822,7 +2226,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1822
2226
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
1823
2227
  }
1824
2228
  }
1825
- \`;var or=\`enable f16;
2229
+ \`;var Wr=\`enable f16;
1826
2230
 
1827
2231
  // Bilinear upsample + channel concat fused \\u2014 full f16 variant.
1828
2232
  // Bilinear weights (wx, wy) and intermediate blends computed in f32; result cast to f16.
@@ -1882,7 +2286,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1882
2286
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
1883
2287
  }
1884
2288
  }
1885
- \`;var we=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?or:rr;let n=e.c/4,u=o.c/4,p=n+u;this.output=r.tensor(a.outH,a.outW,e.c+o.c),this.inputs=[e,o],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,a.outH,a.outW,n,u,p,0])),this.defaultSetup(),this.dispatch=[Math.ceil(a.outW/8),Math.ceil(a.outH/8),p]}};var ir=\`// Bilinear upsample + 1\\xD71 pointwise conv fused.
2289
+ \`;var Fe=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Wr:Cr;let n=e.c/4,s=i.c/4,p=n+s;this.output=r.tensor(o.outH,o.outW,e.c+i.c),this.inputs=[e,i],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o.outH,o.outW,n,s,p,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o.outW/8),Math.ceil(o.outH/8),p]}};var Pr=\`// Bilinear upsample + 1\\xD71 pointwise conv fused.
1886
2290
  // For each output pixel, bilinearly samples the small input for each in_group,
1887
2291
  // immediately applies the 1\\xD71 conv weights, and writes the activated result.
1888
2292
  // Eliminates the intermediate full-resolution upsample buffer.
@@ -1949,7 +2353,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1949
2353
 
1950
2354
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
1951
2355
  }
1952
- \`;var ar=\`enable f16;
2356
+ \`;var Gr=\`enable f16;
1953
2357
 
1954
2358
  // Bilinear upsample + 1\\xD71 pointwise conv fused \\u2014 full f16 variant.
1955
2359
  // Bilinear weights and intermediate blends computed in f32; conv accumulation in f16.
@@ -2016,7 +2420,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2016
2420
 
2017
2421
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
2018
2422
  }
2019
- \`;var ke=class extends f{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?ar:ir;let n=e.c/4,u=a.outChannels/4;this.output=r.tensor(a.outH,a.outW,a.outChannels),this.inputs=[e],this.weights=[r.upload(d(o.weights)),r.upload(d(o.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,a.outH,a.outW,n,u,a.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(a.outW/8),Math.ceil(a.outH/8),u]}};var nr=\`// Bilinear upsample + sigmoid fused.
2423
+ \`;var Ee=class extends f{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Gr:Pr;let n=e.c/4,s=o.outChannels/4;this.output=r.tensor(o.outH,o.outW,o.outChannels),this.inputs=[e],this.weights=[r.upload(m(i.weights)),r.upload(m(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o.outH,o.outW,n,s,o.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o.outW/8),Math.ceil(o.outH/8),s]}};var Br=\`// Bilinear upsample + sigmoid fused.
2020
2424
  // Identical to bilinear_upsample.wgsl except sigmoid is applied at write time.
2021
2425
  // Eliminates the intermediate full-resolution buffer and the separate sigmoid dispatch.
2022
2426
 
@@ -2070,7 +2474,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2070
2474
 
2071
2475
  output_buf[oy * params.out_w * C + ox * C + c] = 1.0 / (1.0 + exp(-result));
2072
2476
  }
2073
- \`;var sr=\`enable f16;
2477
+ \`;var Ur=\`enable f16;
2074
2478
 
2075
2479
  // Bilinear upsample + sigmoid fused \\u2014 full f16 variant.
2076
2480
  // Interpolation computed in f32 for accuracy; sigmoid and result cast to f16.
@@ -2125,7 +2529,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2125
2529
 
2126
2530
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(1.0 / (1.0 + exp(-result)));
2127
2531
  }
2128
- \`;var Te=class extends f{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader");this.shader=r.dtype==="f16"?sr:nr;let a=e.c/4;this.output=r.tensor(o.outH,o.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o.outH,o.outW,a,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o.outW/8),Math.ceil(o.outH/8),a]}};var ur=\`// Composite an RGBA image over a solid background, gated by a 1-ch alpha.
2532
+ \`;var De=class extends f{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader");this.shader=r.dtype==="f16"?Ur:Br;let o=e.c/4;this.output=r.tensor(i.outH,i.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i.outH,i.outW,o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(i.outW/8),Math.ceil(i.outH/8),o]}};var Sr=\`// Composite an RGBA image over a solid background, gated by a 1-ch alpha.
2129
2533
  // Fragment writes the canvas's swapchain texture (premultiplied output).
2130
2534
  //
2131
2535
  // Caller invariants (matched in CompositeSolidWebGPU):
@@ -2170,7 +2574,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2170
2574
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
2171
2575
  return vec4<f32>(rgb, 1.0);
2172
2576
  }
2173
- \`;var pr=\`enable f16;
2577
+ \`;var Lr=\`enable f16;
2174
2578
 
2175
2579
  // Composite an RGBA image over a solid background, gated by a 1-ch alpha.
2176
2580
  // f16 variant: image and alpha are stored as f16; values promote to f32 on
@@ -2219,7 +2623,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2219
2623
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
2220
2624
  return vec4<f32>(rgb, 1.0);
2221
2625
  }
2222
- \`;var Ce=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"pipeline");i(this,"bindGroup");i(this,"uniformBuffer");i(this,"outputView",null);if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeSolid: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match. Run the upscaler first.\`);let a=t.device;this.uniformBuffer=a.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(32);new Uint32Array(n,0,1)[0]=r.w,new Float32Array(n,16,4).set([o[0],o[1],o[2],0]),a.queue.writeBuffer(this.uniformBuffer,0,n);let u=t.dtype==="f16"?pr:ur,p=a.createShaderModule({code:u});this.pipeline=a.createRenderPipeline({layout:"auto",vertex:{module:p,entryPoint:"vs"},fragment:{module:p,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=a.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeSolidWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var lr=\`// Like composite_solid but bg is an NHWC vec4 storage buffer (e.g. virtual
2626
+ \`;var Oe=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"pipeline");a(this,"bindGroup");a(this,"uniformBuffer");a(this,"outputView",null);if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeSolid: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match. Run the upscaler first.\`);let o=t.device;this.uniformBuffer=o.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(32);new Uint32Array(n,0,1)[0]=r.w,new Float32Array(n,16,4).set([i[0],i[1],i[2],0]),o.queue.writeBuffer(this.uniformBuffer,0,n);let s=t.dtype==="f16"?Lr:Sr,p=o.createShaderModule({code:s});this.pipeline=o.createRenderPipeline({layout:"auto",vertex:{module:p,entryPoint:"vs"},fragment:{module:p,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=o.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeSolidWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var Fr=\`// Like composite_solid but bg is an NHWC vec4 storage buffer (e.g. virtual
2223
2627
  // background image, or a blurred copy of the input).
2224
2628
 
2225
2629
  struct VertexOut {
@@ -2261,7 +2665,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2261
2665
  let rgb = fg * a + bgc * (1.0 - a);
2262
2666
  return vec4<f32>(rgb, 1.0);
2263
2667
  }
2264
- \`;var cr=\`enable f16;
2668
+ \`;var Er=\`enable f16;
2265
2669
 
2266
2670
  // Like composite_solid_f16 but bg is an NHWC vec4<f16> storage buffer (e.g. a
2267
2671
  // virtual background image, or a blurred copy of the input).
@@ -2305,7 +2709,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2305
2709
  let rgb = fg * a + bgc * (1.0 - a);
2306
2710
  return vec4<f32>(rgb, 1.0);
2307
2711
  }
2308
- \`;var We=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"pipeline");i(this,"bindGroup");i(this,"uniformBuffer");i(this,"outputView",null);if(r.h!==e.h||r.w!==e.w||r.h!==o.h||r.w!==o.w)throw new Error(\`CompositeImage: image (\${r.h}\\xD7\${r.w}), alpha (\${e.h}\\xD7\${e.w}), and bg (\${o.h}\\xD7\${o.w}) must all match. Run upscaler / resizer first.\`);let a=t.device;this.uniformBuffer=a.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,1)[0]=r.w,a.queue.writeBuffer(this.uniformBuffer,0,n);let u=t.dtype==="f16"?cr:lr,p=a.createShaderModule({code:u});this.pipeline=a.createRenderPipeline({layout:"auto",vertex:{module:p,entryPoint:"vs"},fragment:{module:p,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=a.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:o.buffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeImageWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var dr=\`// Like composite_image but bg is sampled bilinearly \\u2014 bg may be smaller than
2712
+ \`;var Ie=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"pipeline");a(this,"bindGroup");a(this,"uniformBuffer");a(this,"outputView",null);if(r.h!==e.h||r.w!==e.w||r.h!==i.h||r.w!==i.w)throw new Error(\`CompositeImage: image (\${r.h}\\xD7\${r.w}), alpha (\${e.h}\\xD7\${e.w}), and bg (\${i.h}\\xD7\${i.w}) must all match. Run upscaler / resizer first.\`);let o=t.device;this.uniformBuffer=o.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,1)[0]=r.w,o.queue.writeBuffer(this.uniformBuffer,0,n);let s=t.dtype==="f16"?Er:Fr,p=o.createShaderModule({code:s});this.pipeline=o.createRenderPipeline({layout:"auto",vertex:{module:p,entryPoint:"vs"},fragment:{module:p,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=o.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:i.buffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeImageWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var Dr=\`// Like composite_image but bg is sampled bilinearly \\u2014 bg may be smaller than
2309
2713
  // (image, alpha). Used by CompositorBlur to skip the final full-res upsample
2310
2714
  // in the blur pyramid and let this shader's own per-pixel scan do the
2311
2715
  // expansion (the work is already happening here for the composite anyway).
@@ -2370,7 +2774,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2370
2774
  let rgb = fg * a + bgc * (1.0 - a);
2371
2775
  return vec4<f32>(rgb, 1.0);
2372
2776
  }
2373
- \`;var mr=\`enable f16;
2777
+ \`;var Or=\`enable f16;
2374
2778
 
2375
2779
  // f16 storage variant of composite_image_bilinear. bg is at a smaller
2376
2780
  // resolution and is bilinearly sampled to match (image, alpha) at full res.
@@ -2431,7 +2835,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2431
2835
  let rgb = fg * a + bgc * (1.0 - a);
2432
2836
  return vec4<f32>(rgb, 1.0);
2433
2837
  }
2434
- \`;var Pe=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"pipeline");i(this,"bindGroup");i(this,"uniformBuffer");i(this,"outputView",null);if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeImageBilinear: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match.\`);let a=t.device;this.uniformBuffer=a.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16),u=new Uint32Array(n);u[0]=r.w,u[1]=r.h,u[2]=o.w,u[3]=o.h,a.queue.writeBuffer(this.uniformBuffer,0,n);let p=t.dtype==="f16"?mr:dr,l=a.createShaderModule({code:p});this.pipeline=a.createRenderPipeline({layout:"auto",vertex:{module:l,entryPoint:"vs"},fragment:{module:l,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=a.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:o.buffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeImageBilinearWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var fr=\`// Passthrough "compositor" \\u2014 writes the image directly to the canvas
2838
+ \`;var Ae=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"pipeline");a(this,"bindGroup");a(this,"uniformBuffer");a(this,"outputView",null);if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeImageBilinear: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match.\`);let o=t.device;this.uniformBuffer=o.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16),s=new Uint32Array(n);s[0]=r.w,s[1]=r.h,s[2]=i.w,s[3]=i.h,o.queue.writeBuffer(this.uniformBuffer,0,n);let p=t.dtype==="f16"?Or:Dr,l=o.createShaderModule({code:p});this.pipeline=o.createRenderPipeline({layout:"auto",vertex:{module:l,entryPoint:"vs"},fragment:{module:l,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=o.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:e.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:i.buffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositeImageBilinearWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var Ir=\`// Passthrough "compositor" \\u2014 writes the image directly to the canvas
2435
2839
  // swapchain texture with no alpha math and no background. Used by RenderOp
2436
2840
  // when the renderer is in disabled state, so the output canvas reflects
2437
2841
  // the unmodified input frame instead of a stale matted result.
@@ -2469,7 +2873,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2469
2873
  let i = y * params.width + x;
2470
2874
  return vec4<f32>(image[i].rgb, 1.0);
2471
2875
  }
2472
- \`;var hr=\`enable f16;
2876
+ \`;var Ar=\`enable f16;
2473
2877
 
2474
2878
  // Passthrough "compositor" \\u2014 f16 variant. Image is stored as f16; values
2475
2879
  // promote to f32 on read and the fragment writes f32 to the canvas
@@ -2505,7 +2909,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2505
2909
  let i = y * params.width + x;
2506
2910
  return vec4<f32>(vec3<f32>(image[i].rgb), 1.0);
2507
2911
  }
2508
- \`;var Ge=class{constructor(t,r){i(this,"backend",t);i(this,"pipeline");i(this,"bindGroup");i(this,"uniformBuffer");i(this,"outputView",null);let e=t.device;this.uniformBuffer=e.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16);new Uint32Array(o,0,1)[0]=r.w,e.queue.writeBuffer(this.uniformBuffer,0,o);let a=t.dtype==="f16"?hr:fr,n=e.createShaderModule({code:a});this.pipeline=e.createRenderPipeline({layout:"auto",vertex:{module:n,entryPoint:"vs"},fragment:{module:n,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=e.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:this.uniformBuffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositePassthroughWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var gr=\`// Input op \\u2014 sample a regular 2D source texture (RGBA8 unorm) into the NHWC
2912
+ \`;var Me=class{constructor(t,r){a(this,"backend",t);a(this,"pipeline");a(this,"bindGroup");a(this,"uniformBuffer");a(this,"outputView",null);let e=t.device;this.uniformBuffer=e.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let i=new ArrayBuffer(16);new Uint32Array(i,0,1)[0]=r.w,e.queue.writeBuffer(this.uniformBuffer,0,i);let o=t.dtype==="f16"?Ar:Ir,n=e.createShaderModule({code:o});this.pipeline=e.createRenderPipeline({layout:"auto",vertex:{module:n,entryPoint:"vs"},fragment:{module:n,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=e.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.buffer}},{binding:1,resource:{buffer:this.uniformBuffer}}]})}setOutput(t){this.outputView=t.createView()}run(){if(!this.outputView)throw new Error("CompositePassthroughWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),r=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.pipeline),r.setBindGroup(0,this.bindGroup),r.draw(6),r.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null}};var Mr=\`// Input op \\u2014 sample a regular 2D source texture (RGBA8 unorm) into the NHWC
2509
2913
  // vec4<f32> output buffer at the target resolution. Used for ImageBitmap
2510
2914
  // sources, which are uploaded into a persistent staging texture via
2511
2915
  // copyExternalImageToTexture before each dispatch.
@@ -2535,7 +2939,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2535
2939
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
2536
2940
  output_buf[y * params.out_w + x] = rgba;
2537
2941
  }
2538
- \`;var _r=\`enable f16;
2942
+ \`;var Rr=\`enable f16;
2539
2943
 
2540
2944
  // Input op \\u2014 f16 storage variant. Source is sampled as vec4<f32>; only the
2541
2945
  // store is demoted to vec4<f16>.
@@ -2565,7 +2969,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2565
2969
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
2566
2970
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
2567
2971
  }
2568
- \`;var br=\`// Input op \\u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
2972
+ \`;var Hr=\`// Input op \\u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
2569
2973
  // the NHWC vec4<f32> output buffer at the target resolution. Used when the
2570
2974
  // caller passes a VideoFrame to setSource(); requires importExternalTexture
2571
2975
  // to be called in the same task as the dispatch (the texture is invalidated
@@ -2596,7 +3000,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2596
3000
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
2597
3001
  output_buf[y * params.out_w + x] = rgba;
2598
3002
  }
2599
- \`;var vr=\`enable f16;
3003
+ \`;var zr=\`enable f16;
2600
3004
 
2601
3005
  // Input op \\u2014 texture_external + f16 storage. Sample in f32, store as f16.
2602
3006
 
@@ -2625,12 +3029,12 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2625
3029
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
2626
3030
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
2627
3031
  }
2628
- \`;var yi=s=>typeof VideoFrame<"u"&&s instanceof VideoFrame,Be=class{constructor(t,r,e){i(this,"output");i(this,"device");i(this,"dtype");i(this,"sampler");i(this,"uniformBuffer");i(this,"dispatch");i(this,"pipeline2d",null);i(this,"pipelineExternal",null);i(this,"stagingTex",null);i(this,"stagingW",0);i(this,"stagingH",0);i(this,"source",null);this.device=t.device,this.dtype=t.dtype,this.output=t.tensor(r,e,4),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16);new Uint32Array(o,0,2).set([e,r]),this.device.queue.writeBuffer(this.uniformBuffer,0,o),this.dispatch=[Math.ceil(e/8),Math.ceil(r/8),1],this.pipeline2d=this.buildPipeline(this.dtype==="f16"?_r:gr)}setSource(t){this.source=t}run(){if(!this.source)throw new Error("InputWebGPU.run() called before setSource()");yi(this.source)?this.runExternal(this.source):this.run2d(this.source)}run2d(t){this.ensureStagingTexture(t.width,t.height),this.device.queue.copyExternalImageToTexture({source:t,flipY:!1},{texture:this.stagingTex},[t.width,t.height]);let r=this.device.createBindGroup({layout:this.pipeline2d.getBindGroupLayout(0),entries:[{binding:0,resource:this.stagingTex.createView()},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipeline2d,r)}runExternal(t){this.pipelineExternal||(this.pipelineExternal=this.buildPipeline(this.dtype==="f16"?vr:br));let r=this.device.importExternalTexture({source:t}),e=this.device.createBindGroup({layout:this.pipelineExternal.getBindGroupLayout(0),entries:[{binding:0,resource:r},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipelineExternal,e)}ensureStagingTexture(t,r){this.stagingTex&&this.stagingW===t&&this.stagingH===r||(this.stagingTex?.destroy(),this.stagingTex=this.device.createTexture({size:[t,r,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.stagingW=t,this.stagingH=r)}buildPipeline(t){let r=this.device.createShaderModule({code:t});return this.device.createComputePipeline({layout:"auto",compute:{module:r,entryPoint:"main"}})}dispatchOnce(t,r){let e=this.device.createCommandEncoder(),o=e.beginComputePass();o.setPipeline(t),o.setBindGroup(0,r),o.dispatchWorkgroups(...this.dispatch),o.end(),this.device.queue.submit([e.finish()])}};var wi=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,D=class s{constructor(t,r,e){i(this,"device",t);i(this,"canvas",r);i(this,"dtype",e);i(this,"ops");i(this,"presenters");i(this,"canvasContext");i(this,"canvasFormat");i(this,"bytesPerElement");i(this,"contexts",new Map);this.bytesPerElement=e==="f16"?2:4;let o=r.getContext("webgpu");if(!o)throw new Error("Failed to get WebGPU context from canvas");this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.configureContext(o),this.canvasContext=o,this.contexts.set("main",o),this.ops={Conv2d:(a,n,u)=>new oe(this,a,n,u),DepthwiseConv2d:(a,n,u)=>new ie(this,a,n,u),Add:(a,n)=>new ae(this,a,n),Sigmoid:a=>new ne(this,a),Tanh:a=>new se(this,a),ElementwiseMul:(a,n)=>new ue(this,a,n),BilinearUpsample:(a,n)=>new pe(this,a,n),BicubicUpsample:(a,n)=>new le(this,a,n),ChannelConcat:(a,n)=>new ce(this,a,n),Conv2dAdd:(a,n,u,p)=>new de(this,a,n,u,p),ProjResidual:(a,n,u,p)=>new me(this,a,n,u,p),ConcatConv2d:(a,n,u,p)=>new fe(this,a,n,u,p),GatesFused:(a,n,u)=>new he(this,a,n,u),CandUpdateFused:(a,n,u,p,l)=>new ge(this,a,n,u,p,l),ConvExpand:(a,n)=>new _e(this,a,n),CatConv6to2:(a,n,u)=>new be(this,a,n,u),DownAdapter:(a,n,u,p)=>new ve(this,a,n,u,p),UpFinal:(a,n,u)=>new xe(this,a,n,u),UpFinalSkip:(a,n,u,p)=>new ye(this,a,n,u,p),UpsampleConcat:(a,n,u)=>new we(this,a,n,u),UpsampleConv1x1:(a,n,u)=>new ke(this,a,n,u),UpsampleSigmoid:(a,n)=>new Te(this,a,n),Input:(a,n)=>new Be(this,a,n)},this.presenters={CompositeSolid:(a,n,u,p="main")=>{let l=new Ce(this,a,n,u);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositeImage:(a,n,u,p="main")=>{let l=new We(this,a,n,u);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositeImageBilinear:(a,n,u,p="main")=>{let l=new Pe(this,a,n,u);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositePassthrough:(a,n="main")=>{let u=new Ge(this,a);return{run:()=>{u.setOutput(this.getCurrentDisplayTexture(n)),u.run()}}}}}configureContext(t){t.configure({device:this.device,format:this.canvasFormat,alphaMode:"premultiplied"})}attachCanvas(t,r){if(t==="main")throw new Error("attachCanvas: 'main' is reserved for the create() canvas");let e=r.getContext("webgpu");if(!e)throw new Error(\`attachCanvas: failed to get WebGPU context for target '\${t}'\`);this.configureContext(e),this.contexts.set(t,e)}static async isAvailable(){return navigator.gpu?await navigator.gpu.requestAdapter()!==null:!1}static async hasF16Support(){if(!navigator.gpu)return!1;let t=await navigator.gpu.requestAdapter();return t?t.features.has("shader-f16"):!1}static async create(t){let r=t.dtype??"f32",e=t.device;if(e){if(r==="f16"&&!e.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but supplied device lacks \`shader-f16\`")}else{let o=await navigator.gpu.requestAdapter();if(!o)throw new Error("WebGPU adapter not available");if(r==="f16"&&!o.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but adapter lacks \`shader-f16\` feature");e=await o.requestDevice({requiredFeatures:r==="f16"?["shader-f16"]:[]})}return new s(e,t.canvas,r)}getCurrentDisplayTexture(t="main"){let r=this.contexts.get(t);if(!r)throw new Error(\`getCurrentDisplayTexture: no canvas attached for target '\${t}'\`);return r.getCurrentTexture()}tensor(t,r,e,o){let n=t*r*e*this.bytesPerElement,u=this.device.createBuffer({size:n,usage:wi,mappedAtCreation:o!==void 0});if(o!==void 0){let p=u.getMappedRange();this.writeView(p,o),u.unmap()}return{h:t,w:r,c:e,buffer:u}}upload(t){let e=t.length*this.bytesPerElement,o=this.device.createBuffer({size:e,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});return this.writeView(o.getMappedRange(),t),o.unmap(),{buffer:o}}writeView(t,r){let e=this.dtype==="f16",o=r instanceof Uint16Array;if(e===o){e?new Uint16Array(t).set(r):new Float32Array(t).set(r);return}e?new Uint16Array(t).set(re(r)):new Float32Array(t).set(I(r))}async readback(t){let r=this.device.createBuffer({size:t.buffer.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),e=this.device.createCommandEncoder();e.copyBufferToBuffer(t.buffer,0,r,0,t.buffer.size),this.device.queue.submit([e.finish()]),await r.mapAsync(GPUMapMode.READ);let o=r.getMappedRange(),a=this.dtype==="f16"?I(new Uint16Array(o.slice(0))):new Float32Array(o.slice(0));return r.unmap(),r.destroy(),a}copyTensor(t,r){if(t.buffer.size!==r.buffer.size)throw new Error(\`copyTensor: size mismatch (src \${t.buffer.size} vs dst \${r.buffer.size})\`);let e=this.device.createCommandEncoder();e.copyBufferToBuffer(t.buffer,0,r.buffer,0,t.buffer.size),this.device.queue.submit([e.finish()])}async sync(){await this.device.queue.onSubmittedWorkDone()}destroy(){this.device.destroy()}};var ki=\`#version 300 es
3032
+ \`;var aa=u=>typeof VideoFrame<"u"&&u instanceof VideoFrame,Re=class{constructor(t,r,e){a(this,"output");a(this,"device");a(this,"dtype");a(this,"sampler");a(this,"uniformBuffer");a(this,"dispatch");a(this,"pipeline2d",null);a(this,"pipelineExternal",null);a(this,"stagingTex",null);a(this,"stagingW",0);a(this,"stagingH",0);a(this,"source",null);this.device=t.device,this.dtype=t.dtype,this.output=t.tensor(r,e,4),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let i=new ArrayBuffer(16);new Uint32Array(i,0,2).set([e,r]),this.device.queue.writeBuffer(this.uniformBuffer,0,i),this.dispatch=[Math.ceil(e/8),Math.ceil(r/8),1],this.pipeline2d=this.buildPipeline(this.dtype==="f16"?Rr:Mr)}setSource(t){this.source=t}run(){if(!this.source)throw new Error("InputWebGPU.run() called before setSource()");aa(this.source)?this.runExternal(this.source):this.run2d(this.source)}run2d(t){this.ensureStagingTexture(t.width,t.height),this.device.queue.copyExternalImageToTexture({source:t,flipY:!1},{texture:this.stagingTex},[t.width,t.height]);let r=this.device.createBindGroup({layout:this.pipeline2d.getBindGroupLayout(0),entries:[{binding:0,resource:this.stagingTex.createView()},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipeline2d,r)}runExternal(t){this.pipelineExternal||(this.pipelineExternal=this.buildPipeline(this.dtype==="f16"?zr:Hr));let r=this.device.importExternalTexture({source:t}),e=this.device.createBindGroup({layout:this.pipelineExternal.getBindGroupLayout(0),entries:[{binding:0,resource:r},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipelineExternal,e)}ensureStagingTexture(t,r){this.stagingTex&&this.stagingW===t&&this.stagingH===r||(this.stagingTex?.destroy(),this.stagingTex=this.device.createTexture({size:[t,r,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.stagingW=t,this.stagingH=r)}buildPipeline(t){let r=this.device.createShaderModule({code:t});return this.device.createComputePipeline({layout:"auto",compute:{module:r,entryPoint:"main"}})}dispatchOnce(t,r){let e=this.device.createCommandEncoder(),i=e.beginComputePass();i.setPipeline(t),i.setBindGroup(0,r),i.dispatchWorkgroups(...this.dispatch),i.end(),this.device.queue.submit([e.finish()])}};var na=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,R=class u{constructor(t,r,e){a(this,"device",t);a(this,"canvas",r);a(this,"dtype",e);a(this,"ops");a(this,"presenters");a(this,"canvasContext");a(this,"canvasFormat");a(this,"bytesPerElement");a(this,"contexts",new Map);this.bytesPerElement=e==="f16"?2:4;let i=r.getContext("webgpu");if(!i)throw new Error("Failed to get WebGPU context from canvas");this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.configureContext(i),this.canvasContext=i,this.contexts.set("main",i),this.ops={Conv2d:(o,n,s)=>new le(this,o,n,s),ConvTranspose2d:(o,n,s)=>new ce(this,o,n,s),DepthwiseConv2d:(o,n,s)=>new de(this,o,n,s),Add:(o,n)=>new me(this,o,n),Sigmoid:o=>new fe(this,o),Tanh:o=>new he(this,o),ElementwiseMul:(o,n)=>new _e(this,o,n),Warp:(o,n,s)=>new ge(this,o,n,s),Stabilize:(o,n,s,p,l)=>new be(this,o,n,s,p,l),BilinearUpsample:(o,n)=>new ve(this,o,n),Crop:(o,n)=>new xe(this,o,n),BicubicUpsample:(o,n)=>new ye(this,o,n),ChannelConcat:(o,n)=>new we(this,o,n),Conv2dAdd:(o,n,s,p)=>new ke(this,o,n,s,p),ProjResidual:(o,n,s,p)=>new Te(this,o,n,s,p),ConcatConv2d:(o,n,s,p)=>new Ce(this,o,n,s,p),GatesFused:(o,n,s)=>new We(this,o,n,s),CandUpdateFused:(o,n,s,p,l)=>new Pe(this,o,n,s,p,l),ConvExpand:(o,n)=>new Ge(this,o,n),CatConv6to2:(o,n,s)=>new Be(this,o,n,s),DownAdapter:(o,n,s,p)=>new Ue(this,o,n,s,p),UpFinal:(o,n,s)=>new Se(this,o,n,s),UpFinalSkip:(o,n,s,p)=>new Le(this,o,n,s,p),UpsampleConcat:(o,n,s)=>new Fe(this,o,n,s),UpsampleConv1x1:(o,n,s)=>new Ee(this,o,n,s),UpsampleSigmoid:(o,n)=>new De(this,o,n),Input:(o,n)=>new Re(this,o,n)},this.presenters={CompositeSolid:(o,n,s,p="main")=>{let l=new Oe(this,o,n,s);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositeImage:(o,n,s,p="main")=>{let l=new Ie(this,o,n,s);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositeImageBilinear:(o,n,s,p="main")=>{let l=new Ae(this,o,n,s);return{run:()=>{l.setOutput(this.getCurrentDisplayTexture(p)),l.run()}}},CompositePassthrough:(o,n="main")=>{let s=new Me(this,o);return{run:()=>{s.setOutput(this.getCurrentDisplayTexture(n)),s.run()}}}}}configureContext(t){t.configure({device:this.device,format:this.canvasFormat,alphaMode:"premultiplied"})}attachCanvas(t,r){if(t==="main")throw new Error("attachCanvas: 'main' is reserved for the create() canvas");let e=r.getContext("webgpu");if(!e)throw new Error(\`attachCanvas: failed to get WebGPU context for target '\${t}'\`);this.configureContext(e),this.contexts.set(t,e)}static async isAvailable(){return navigator.gpu?await navigator.gpu.requestAdapter()!==null:!1}static async hasF16Support(){if(!navigator.gpu)return!1;let t=await navigator.gpu.requestAdapter();return t?t.features.has("shader-f16"):!1}static async create(t){let r=t.dtype??"f32",e=t.device;if(e){if(r==="f16"&&!e.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but supplied device lacks \`shader-f16\`")}else{let i=await navigator.gpu.requestAdapter();if(!i)throw new Error("WebGPU adapter not available");if(r==="f16"&&!i.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but adapter lacks \`shader-f16\` feature");e=await i.requestDevice({requiredFeatures:r==="f16"?["shader-f16"]:[]})}return new u(e,t.canvas,r)}getCurrentDisplayTexture(t="main"){let r=this.contexts.get(t);if(!r)throw new Error(\`getCurrentDisplayTexture: no canvas attached for target '\${t}'\`);return r.getCurrentTexture()}tensor(t,r,e,i){let n=t*r*e*this.bytesPerElement,s=this.device.createBuffer({size:n,usage:na,mappedAtCreation:i!==void 0});if(i!==void 0){let p=s.getMappedRange();this.writeView(p,i),s.unmap()}return{h:t,w:r,c:e,buffer:s}}upload(t){let e=t.length*this.bytesPerElement,i=this.device.createBuffer({size:e,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});return this.writeView(i.getMappedRange(),t),i.unmap(),{buffer:i}}writeView(t,r){let e=this.dtype==="f16",i=r instanceof Uint16Array;if(e===i){e?new Uint16Array(t).set(r):new Float32Array(t).set(r);return}e?new Uint16Array(t).set(pe(r)):new Float32Array(t).set(A(r))}async readback(t){let r=this.device.createBuffer({size:t.buffer.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),e=this.device.createCommandEncoder();e.copyBufferToBuffer(t.buffer,0,r,0,t.buffer.size),this.device.queue.submit([e.finish()]),await r.mapAsync(GPUMapMode.READ);let i=r.getMappedRange(),o=this.dtype==="f16"?A(new Uint16Array(i.slice(0))):new Float32Array(i.slice(0));return r.unmap(),r.destroy(),o}copyTensor(t,r){if(t.buffer.size!==r.buffer.size)throw new Error(\`copyTensor: size mismatch (src \${t.buffer.size} vs dst \${r.buffer.size})\`);let e=this.device.createCommandEncoder();e.copyBufferToBuffer(t.buffer,0,r.buffer,0,t.buffer.size),this.device.queue.submit([e.finish()])}async sync(){await this.device.queue.onSubmittedWorkDone()}destroy(){this.device.destroy()}};var sa=\`#version 300 es
2629
3033
  const vec2 VERTS[6] = vec2[6](
2630
3034
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
2631
3035
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
2632
3036
  );
2633
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,h=class{constructor(t){i(this,"backend",t);i(this,"shader","");i(this,"program");i(this,"samplers",[]);i(this,"uniformInts",{})}makeTexture(t,r,e){let o=this.backend.gl,a=this.backend.textureFormat,n=this.backend.toTextureView(t),u=o.createTexture();return o.bindTexture(o.TEXTURE_2D,u),o.texImage2D(o.TEXTURE_2D,0,a.internalFormat,r,e,0,a.format,a.type,n),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.NEAREST),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.NEAREST),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE),u}defaultSetup(){let t=this.backend.gl,r=t.createShader(t.VERTEX_SHADER);t.shaderSource(r,ki),t.compileShader(r);let e=t.createShader(t.FRAGMENT_SHADER);if(t.shaderSource(e,this.shader),t.compileShader(e),!t.getShaderParameter(e,t.COMPILE_STATUS))throw new Error(\`GLSL compile error: \${t.getShaderInfoLog(e)}\`);if(this.program=t.createProgram(),t.attachShader(this.program,r),t.attachShader(this.program,e),t.linkProgram(this.program),!t.getProgramParameter(this.program,t.LINK_STATUS))throw new Error(\`GLSL link error: \${t.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),this.samplers.forEach(({name:r,texture:e},o)=>{t.activeTexture(t.TEXTURE0+o),t.bindTexture(t.TEXTURE_2D,e),t.uniform1i(t.getUniformLocation(this.program,r),o)});for(let[r,e]of Object.entries(this.uniformInts))t.uniform1i(t.getUniformLocation(this.program,r),e);t.bindFramebuffer(t.FRAMEBUFFER,this.backend.fbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.output.texture,0),t.viewport(0,0,this.dispatch[0],this.dispatch[1]),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var xr=\`#version 300 es
3037
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,h=class{constructor(t){a(this,"backend",t);a(this,"shader","");a(this,"program");a(this,"samplers",[]);a(this,"uniformInts",{});a(this,"uniformFloats",{})}makeTexture(t,r,e){let i=this.backend.gl,o=this.backend.textureFormat,n=this.backend.toTextureView(t),s=i.createTexture();return i.bindTexture(i.TEXTURE_2D,s),i.texImage2D(i.TEXTURE_2D,0,o.internalFormat,r,e,0,o.format,o.type,n),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),s}defaultSetup(){let t=this.backend.gl,r=t.createShader(t.VERTEX_SHADER);t.shaderSource(r,sa),t.compileShader(r);let e=t.createShader(t.FRAGMENT_SHADER);if(t.shaderSource(e,this.shader),t.compileShader(e),!t.getShaderParameter(e,t.COMPILE_STATUS))throw new Error(\`GLSL compile error: \${t.getShaderInfoLog(e)}\`);if(this.program=t.createProgram(),t.attachShader(this.program,r),t.attachShader(this.program,e),t.linkProgram(this.program),!t.getProgramParameter(this.program,t.LINK_STATUS))throw new Error(\`GLSL link error: \${t.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),this.samplers.forEach(({name:r,texture:e},i)=>{t.activeTexture(t.TEXTURE0+i),t.bindTexture(t.TEXTURE_2D,e),t.uniform1i(t.getUniformLocation(this.program,r),i)});for(let[r,e]of Object.entries(this.uniformInts))t.uniform1i(t.getUniformLocation(this.program,r),e);for(let[r,e]of Object.entries(this.uniformFloats))t.uniform1f(t.getUniformLocation(this.program,r),e);t.bindFramebuffer(t.FRAMEBUFFER,this.backend.fbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.output.texture,0),t.viewport(0,0,this.dispatch[0],this.dispatch[1]),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var Vr=\`#version 300 es
2634
3038
  // Conv2d \\u2014 handles all variants: 1\\xD71 (pointwise), 3\\xD73, 5\\xD75, strided, BN-fused.
2635
3039
  //
2636
3040
  // Tensor layout: NHWC vec4 \\u2014 texture dimensions (W * C/4, H).
@@ -2663,7 +3067,7 @@ uniform int u_kernel_w;
2663
3067
  uniform int u_stride;
2664
3068
  uniform int u_pad_top;
2665
3069
  uniform int u_pad_left;
2666
- uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu
3070
+ uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu, 3 = leaky(0.1)
2667
3071
 
2668
3072
  out vec4 fragColor;
2669
3073
 
@@ -2703,10 +3107,80 @@ void main() {
2703
3107
 
2704
3108
  if (u_activation == 1) result = clamp(result, 0.0, 6.0);
2705
3109
  else if (u_activation == 2) result = max(result, vec4(0.0));
3110
+ else if (u_activation == 3) result = max(result, 0.1 * result);
2706
3111
 
2707
3112
  fragColor = result;
2708
3113
  }
2709
- \`;var Ue=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",xr);let n=w(e.h,a.kernel,a.stride,a.padding),u=w(e.w,a.kernel,a.stride,a.padding),p=e.c/4,l=a.outChannels/4,c=k(a.padding,e.h,n,a.kernel,a.stride),m=k(a.padding,e.w,u,a.kernel,a.stride),_=d(o.weights),g=d(o.bias),x=this.makeTexture(_,p*4,a.kernel*a.kernel*l),y=this.makeTexture(g,l,1),T=u*l,P=this.makeTexture(null,T,n);this.output={h:n,w:u,c:a.outChannels,texture:P,texW:T,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:x},{name:"u_bias",texture:y}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_in_c_groups:p,u_out_c_groups:l,u_kernel_h:a.kernel,u_kernel_w:a.kernel,u_stride:a.stride,u_pad_top:c,u_pad_left:m,u_activation:a.activation==="relu6"?1:a.activation==="relu"?2:0},this.defaultSetup(),this.dispatch=[T,n]}};var yr=\`#version 300 es
3114
+ \`;var He=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",Vr);let n=T(e.h,o.kernel,o.stride,o.padding),s=T(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=o.outChannels/4,c=C(o.padding,e.h,n,o.kernel,o.stride),d=C(o.padding,e.w,s,o.kernel,o.stride),_=m(i.weights),b=m(i.bias),g=this.makeTexture(_,p*4,o.kernel*o.kernel*l),v=this.makeTexture(b,l,1),x=s*l,k=this.makeTexture(null,x,n);this.output={h:n,w:s,c:o.outChannels,texture:k,texW:x,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:g},{name:"u_bias",texture:v}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_in_c_groups:p,u_out_c_groups:l,u_kernel_h:o.kernel,u_kernel_w:o.kernel,u_stride:o.stride,u_pad_top:c,u_pad_left:d,u_activation:o.activation==="relu6"?1:o.activation==="relu"?2:o.activation==="leaky"?3:0},this.defaultSetup(),this.dispatch=[x,n]}};var Nr=\`#version 300 es
3115
+ // ConvTranspose2d \\u2014 gather form. Identical texture layouts + mat4 weight
3116
+ // semantics as conv2d.glsl; only the spatial mapping differs:
3117
+ // in_y = (y_out + pad - ky) / stride (must divide evenly + be in bounds)
3118
+ // No explicit kernel flip \\u2014 the (y_out + pad - ky) indexing carries it.
3119
+
3120
+ precision highp float;
3121
+ precision highp int;
3122
+
3123
+ uniform sampler2D u_input; // (in_W * in_C_groups, in_H)
3124
+ uniform sampler2D u_weights; // (in_C_groups * 4, K\\xB2 * out_C_groups)
3125
+ uniform sampler2D u_bias; // (out_C_groups, 1)
3126
+
3127
+ uniform int u_in_w;
3128
+ uniform int u_in_h;
3129
+ uniform int u_in_c_groups;
3130
+ uniform int u_out_c_groups;
3131
+ uniform int u_kernel_h;
3132
+ uniform int u_kernel_w;
3133
+ uniform int u_stride;
3134
+ uniform int u_pad_top;
3135
+ uniform int u_pad_left;
3136
+ uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu, 3 = leaky(0.1)
3137
+
3138
+ out vec4 fragColor;
3139
+
3140
+ void main() {
3141
+ int fx = int(gl_FragCoord.x);
3142
+ int fy = int(gl_FragCoord.y);
3143
+ int x_out = fx / u_out_c_groups;
3144
+ int y_out = fy;
3145
+ int o_group = fx - x_out * u_out_c_groups;
3146
+
3147
+ vec4 result = texelFetch(u_bias, ivec2(o_group, 0), 0);
3148
+
3149
+ for (int ky = 0; ky < u_kernel_h; ky++) {
3150
+ for (int kx = 0; kx < u_kernel_w; kx++) {
3151
+ int iy_num = y_out + u_pad_top - ky;
3152
+ int ix_num = x_out + u_pad_left - kx;
3153
+ if (iy_num < 0 || ix_num < 0) continue;
3154
+ if ((iy_num % u_stride) != 0 || (ix_num % u_stride) != 0) continue;
3155
+ int in_y = iy_num / u_stride;
3156
+ int in_x = ix_num / u_stride;
3157
+ if (in_y >= u_in_h || in_x >= u_in_w) continue;
3158
+
3159
+ int z = ky * u_kernel_w + kx;
3160
+ int w_row = z * u_out_c_groups + o_group;
3161
+
3162
+ for (int i = 0; i < u_in_c_groups; i++) {
3163
+ vec4 in_val = texelFetch(u_input, ivec2(in_x * u_in_c_groups + i, in_y), 0);
3164
+
3165
+ int base = i * 4;
3166
+ mat4 w = mat4(
3167
+ texelFetch(u_weights, ivec2(base, w_row), 0),
3168
+ texelFetch(u_weights, ivec2(base + 1, w_row), 0),
3169
+ texelFetch(u_weights, ivec2(base + 2, w_row), 0),
3170
+ texelFetch(u_weights, ivec2(base + 3, w_row), 0)
3171
+ );
3172
+ result += w * in_val;
3173
+ }
3174
+ }
3175
+ }
3176
+
3177
+ if (u_activation == 1) result = clamp(result, 0.0, 6.0);
3178
+ else if (u_activation == 2) result = max(result, vec4(0.0));
3179
+ else if (u_activation == 3) result = max(result, 0.1 * result);
3180
+
3181
+ fragColor = result;
3182
+ }
3183
+ \`;var ze=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",Nr);let n=M(e.h,o.kernel,o.stride,o.padding),s=M(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=o.outChannels/4,c=m(i.weights),d=m(i.bias),_=this.makeTexture(c,p*4,o.kernel*o.kernel*l),b=this.makeTexture(d,l,1),g=s*l,v=this.makeTexture(null,g,n);this.output={h:n,w:s,c:o.outChannels,texture:v,texW:g,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:_},{name:"u_bias",texture:b}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_in_c_groups:p,u_out_c_groups:l,u_kernel_h:o.kernel,u_kernel_w:o.kernel,u_stride:o.stride,u_pad_top:o.padding,u_pad_left:o.padding,u_activation:o.activation==="relu6"?1:o.activation==="relu"?2:o.activation==="leaky"?3:0},this.defaultSetup(),this.dispatch=[g,n]}};var $r=\`#version 300 es
2710
3184
  // Depthwise Conv2d \\u2014 groups = in_channels (each channel convolved independently).
2711
3185
  //
2712
3186
  // Weight layout: (C_groups, K\\xB2) RGBA32F texture \\u2014 contrast with conv2d which uses mat4.
@@ -2763,7 +3237,7 @@ void main() {
2763
3237
 
2764
3238
  fragColor = result;
2765
3239
  }
2766
- \`;var Se=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",yr);let n=w(e.h,a.kernel,a.stride,a.padding),u=w(e.w,a.kernel,a.stride,a.padding),p=e.c/4,l=k(a.padding,e.h,n,a.kernel,a.stride),c=k(a.padding,e.w,u,a.kernel,a.stride),m=d(o.weights),_=d(o.bias),g=this.makeTexture(m,p,a.kernel*a.kernel),x=this.makeTexture(_,p,1),y=u*p,T=this.makeTexture(null,y,n);this.output={h:n,w:u,c:e.c,texture:T,texW:y,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:g},{name:"u_bias",texture:x}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_c_groups:p,u_kernel_h:a.kernel,u_kernel_w:a.kernel,u_stride:a.stride,u_pad_top:l,u_pad_left:c,u_apply_relu6:a.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[y,n]}};var wr=\`#version 300 es
3240
+ \`;var Ve=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",$r);let n=T(e.h,o.kernel,o.stride,o.padding),s=T(e.w,o.kernel,o.stride,o.padding),p=e.c/4,l=C(o.padding,e.h,n,o.kernel,o.stride),c=C(o.padding,e.w,s,o.kernel,o.stride),d=m(i.weights),_=m(i.bias),b=this.makeTexture(d,p,o.kernel*o.kernel),g=this.makeTexture(_,p,1),v=s*p,x=this.makeTexture(null,v,n);this.output={h:n,w:s,c:e.c,texture:x,texW:v,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:b},{name:"u_bias",texture:g}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_c_groups:p,u_kernel_h:o.kernel,u_kernel_w:o.kernel,u_stride:o.stride,u_pad_top:l,u_pad_left:c,u_apply_relu6:o.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[v,n]}};var Xr=\`#version 300 es
2767
3241
  // Element-wise add \\u2014 both inputs and output share the same texture dimensions.
2768
3242
  // Works for any 2D layout; used here with a flat (nVec4, 1) texture.
2769
3243
 
@@ -2778,7 +3252,7 @@ void main() {
2778
3252
  ivec2 fc = ivec2(gl_FragCoord.xy);
2779
3253
  fragColor = texelFetch(u_input_a, fc, 0) + texelFetch(u_input_b, fc, 0);
2780
3254
  }
2781
- \`;var Le=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",wr);let a=e,n=this.makeTexture(null,a.texW,a.texH);this.output={h:e.h,w:e.w,c:e.c,texture:n,texW:a.texW,texH:a.texH},this.inputs=[e,o],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:o.texture}],this.defaultSetup(),this.dispatch=[a.texW,a.texH]}};var kr=\`#version 300 es
3255
+ \`;var Ne=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Xr);let o=e,n=this.makeTexture(null,o.texW,o.texH);this.output={h:e.h,w:e.w,c:e.c,texture:n,texW:o.texW,texH:o.texH},this.inputs=[e,i],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:i.texture}],this.defaultSetup(),this.dispatch=[o.texW,o.texH]}};var jr=\`#version 300 es
2782
3256
  // Element-wise sigmoid \\u2014 works on any texture layout (flat or spatial).
2783
3257
 
2784
3258
  precision highp float;
@@ -2787,39 +3261,130 @@ uniform sampler2D u_input;
2787
3261
 
2788
3262
  out vec4 fragColor;
2789
3263
 
2790
- void main() {
2791
- vec4 x = texelFetch(u_input, ivec2(gl_FragCoord.xy), 0);
2792
- fragColor = 1.0 / (1.0 + exp(-x));
3264
+ void main() {
3265
+ vec4 x = texelFetch(u_input, ivec2(gl_FragCoord.xy), 0);
3266
+ fragColor = 1.0 / (1.0 + exp(-x));
3267
+ }
3268
+ \`;var $e=class extends h{constructor(r,e){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",jr);let i=e,o=this.makeTexture(null,i.texW,i.texH);this.output={h:e.h,w:e.w,c:e.c,texture:o,texW:i.texW,texH:i.texH},this.inputs=[e],this.samplers=[{name:"u_input",texture:i.texture}],this.defaultSetup(),this.dispatch=[i.texW,i.texH]}};var qr=\`#version 300 es
3269
+ // Element-wise tanh \\u2014 used by ConvGRU candidate activation.
3270
+ // Layout-agnostic (flat or spatial); GLSL tanh is element-wise on vec4.
3271
+
3272
+ precision highp float;
3273
+
3274
+ uniform sampler2D u_input;
3275
+
3276
+ out vec4 fragColor;
3277
+
3278
+ void main() {
3279
+ fragColor = tanh(texelFetch(u_input, ivec2(gl_FragCoord.xy), 0));
3280
+ }
3281
+ \`;var Xe=class extends h{constructor(r,e){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",qr);let i=e,o=this.makeTexture(null,i.texW,i.texH);this.output={h:e.h,w:e.w,c:e.c,texture:o,texW:i.texW,texH:i.texH},this.inputs=[e],this.samplers=[{name:"u_input",texture:i.texture}],this.defaultSetup(),this.dispatch=[i.texW,i.texH]}};var Kr=\`#version 300 es
3282
+ // Element-wise multiply \\u2014 used in ConvGRU for r \\u2299 h_prev.
3283
+ // Same shape constraint as add.glsl.
3284
+
3285
+ precision highp float;
3286
+
3287
+ uniform sampler2D u_input_a;
3288
+ uniform sampler2D u_input_b;
3289
+
3290
+ out vec4 fragColor;
3291
+
3292
+ void main() {
3293
+ ivec2 fc = ivec2(gl_FragCoord.xy);
3294
+ fragColor = texelFetch(u_input_a, fc, 0) * texelFetch(u_input_b, fc, 0);
3295
+ }
3296
+ \`;var je=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Kr);let o=e,n=this.makeTexture(null,o.texW,o.texH);this.output={h:e.h,w:e.w,c:e.c,texture:n,texW:o.texW,texH:o.texH},this.inputs=[e,i],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:i.texture}],this.defaultSetup(),this.dispatch=[o.texW,o.texH]}};var Yr=\`#version 300 es
3297
+ // Bilinear gather-warp. out[p] = sample(source, p + flow_scale\\xB7flow[p].xy),
3298
+ // edge-clamped. Source + flow are 4-ch (1 group), same resolution; flow in .xy.
3299
+
3300
+ precision highp float;
3301
+ precision highp int;
3302
+
3303
+ uniform sampler2D u_source; // (W, H)
3304
+ uniform sampler2D u_flow; // (W, H), flow in .xy
3305
+ uniform int u_w;
3306
+ uniform int u_h;
3307
+ uniform float u_flow_scale;
3308
+
3309
+ out vec4 fragColor;
3310
+
3311
+ vec4 samp(int x, int y) {
3312
+ int cx = clamp(x, 0, u_w - 1);
3313
+ int cy = clamp(y, 0, u_h - 1);
3314
+ return texelFetch(u_source, ivec2(cx, cy), 0);
3315
+ }
3316
+
3317
+ void main() {
3318
+ int x = int(gl_FragCoord.x);
3319
+ int y = int(gl_FragCoord.y);
3320
+
3321
+ vec2 f = texelFetch(u_flow, ivec2(x, y), 0).xy;
3322
+ float sx = clamp(float(x) + u_flow_scale * f.x, 0.0, float(u_w - 1));
3323
+ float sy = clamp(float(y) + u_flow_scale * f.y, 0.0, float(u_h - 1));
3324
+
3325
+ int x0 = int(floor(sx));
3326
+ int y0 = int(floor(sy));
3327
+ float tx = sx - float(x0);
3328
+ float ty = sy - float(y0);
3329
+
3330
+ vec4 top = mix(samp(x0, y0), samp(x0 + 1, y0), tx);
3331
+ vec4 bot = mix(samp(x0, y0 + 1), samp(x0 + 1, y0 + 1), tx);
3332
+ fragColor = mix(top, bot, ty);
2793
3333
  }
2794
- \`;var Fe=class extends h{constructor(r,e){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",kr);let o=e,a=this.makeTexture(null,o.texW,o.texH);this.output={h:e.h,w:e.w,c:e.c,texture:a,texW:o.texW,texH:o.texH},this.inputs=[e],this.samplers=[{name:"u_input",texture:o.texture}],this.defaultSetup(),this.dispatch=[o.texW,o.texH]}};var Tr=\`#version 300 es
2795
- // Element-wise tanh \\u2014 used by ConvGRU candidate activation.
2796
- // Layout-agnostic (flat or spatial); GLSL tanh is element-wise on vec4.
3334
+ \`;var qe=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Yr);let n=e.w,s=e.h,p=this.makeTexture(null,n,s);this.output={h:s,w:n,c:e.c,texture:p,texW:n,texH:s},this.inputs=[e,i],this.samplers=[{name:"u_source",texture:e.texture},{name:"u_flow",texture:i.texture}],this.uniformInts={u_w:n,u_h:s},this.uniformFloats={u_flow_scale:o.flowScale},this.defaultSetup(),this.dispatch=[n,s]}};var Qr=\`#version 300 es
3335
+ // Flow-gated temporal stabilizer. Per pixel:
3336
+ // env = max(|flow.xy|, release\\xB7envPrev.y) peak-hold
3337
+ // g = max(clamp((env - tLo)/(tHi - tLo), 0, 1), leak)
3338
+ // out = vec4((g\\xB7pred + (1-g)\\xB7ref).x, env, 0, 0)
2797
3339
 
2798
3340
  precision highp float;
3341
+ precision highp int;
2799
3342
 
2800
- uniform sampler2D u_input;
3343
+ uniform sampler2D u_flow;
3344
+ uniform sampler2D u_pred;
3345
+ uniform sampler2D u_ref;
3346
+ uniform sampler2D u_env_prev;
3347
+ uniform int u_w;
3348
+ uniform int u_h;
3349
+ uniform float u_t_lo;
3350
+ uniform float u_t_hi;
3351
+ uniform float u_leak;
3352
+ uniform float u_release;
3353
+ uniform float u_t_div;
3354
+ uniform float u_div_scale;
3355
+ uniform int u_step_x;
3356
+ uniform int u_step_y;
2801
3357
 
2802
3358
  out vec4 fragColor;
2803
3359
 
2804
3360
  void main() {
2805
- fragColor = tanh(texelFetch(u_input, ivec2(gl_FragCoord.xy), 0));
2806
- }
2807
- \`;var Ee=class extends h{constructor(r,e){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Tr);let o=e,a=this.makeTexture(null,o.texW,o.texH);this.output={h:e.h,w:e.w,c:e.c,texture:a,texW:o.texW,texH:o.texH},this.inputs=[e],this.samplers=[{name:"u_input",texture:o.texture}],this.defaultSetup(),this.dispatch=[o.texW,o.texH]}};var Cr=\`#version 300 es
2808
- // Element-wise multiply \\u2014 used in ConvGRU for r \\u2299 h_prev.
2809
- // Same shape constraint as add.glsl.
3361
+ int x = int(gl_FragCoord.x);
3362
+ int y = int(gl_FragCoord.y);
2810
3363
 
2811
- precision highp float;
3364
+ float mag = length(texelFetch(u_flow, ivec2(x, y), 0).xy);
3365
+ float envPrev = texelFetch(u_env_prev, ivec2(x, y), 0).y;
3366
+ float env = max(mag, u_release * envPrev);
2812
3367
 
2813
- uniform sampler2D u_input_a;
2814
- uniform sampler2D u_input_b;
3368
+ // Flow divergence over a \\xB1step finite-difference (clamped to the edges).
3369
+ int xr = min(x + u_step_x, u_w - 1);
3370
+ int xl = max(x - u_step_x, 0);
3371
+ int yd = min(y + u_step_y, u_h - 1);
3372
+ int yu = max(y - u_step_y, 0);
3373
+ float dfx = texelFetch(u_flow, ivec2(xr, y), 0).x - texelFetch(u_flow, ivec2(xl, y), 0).x;
3374
+ float dfy = texelFetch(u_flow, ivec2(x, yd), 0).y - texelFetch(u_flow, ivec2(x, yu), 0).y;
3375
+ float divg = abs(dfx + dfy);
2815
3376
 
2816
- out vec4 fragColor;
3377
+ float gMag = clamp((env - u_t_lo) / max(u_t_hi - u_t_lo, 1e-3), 0.0, 1.0);
3378
+ float gDiv = clamp((divg - u_t_div) / max(u_div_scale, 1e-3), 0.0, 1.0);
3379
+ float g = max(max(gMag, gDiv), u_leak);
2817
3380
 
2818
- void main() {
2819
- ivec2 fc = ivec2(gl_FragCoord.xy);
2820
- fragColor = texelFetch(u_input_a, fc, 0) * texelFetch(u_input_b, fc, 0);
3381
+ float pred = texelFetch(u_pred, ivec2(x, y), 0).x;
3382
+ float refv = texelFetch(u_ref, ivec2(x, y), 0).x;
3383
+ float stab = g * pred + (1.0 - g) * refv;
3384
+
3385
+ fragColor = vec4(stab, env, 0.0, 0.0);
2821
3386
  }
2822
- \`;var Oe=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Cr);let a=e,n=this.makeTexture(null,a.texW,a.texH);this.output={h:e.h,w:e.w,c:e.c,texture:n,texW:a.texW,texH:a.texH},this.inputs=[e,o],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:o.texture}],this.defaultSetup(),this.dispatch=[a.texW,a.texH]}};var Wr=\`#version 300 es
3387
+ \`;var Ke=class extends h{constructor(r,e,i,o,n,s){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Qr);let p=e.w,l=e.h,c=this.makeTexture(null,p,l);this.output={h:l,w:p,c:4,texture:c,texW:p,texH:l},this.inputs=[e,i,o,n],this.samplers=[{name:"u_flow",texture:e.texture},{name:"u_pred",texture:i.texture},{name:"u_ref",texture:o.texture},{name:"u_env_prev",texture:n.texture}],this.uniformInts={u_w:p,u_h:l,u_step_x:s.stepX,u_step_y:s.stepY},this.uniformFloats={u_t_lo:s.tLo,u_t_hi:s.tHi,u_leak:s.leak,u_release:s.release,u_t_div:s.tDiv,u_div_scale:s.divScale},this.defaultSetup(),this.dispatch=[p,l]}};var Jr=\`#version 300 es
2823
3388
  // Bilinear upsample (arbitrary scale) \\u2014 align_corners=False.
2824
3389
  //
2825
3390
  // Hardware texture filtering can't be used: adjacent texels in x belong to
@@ -2870,7 +3435,21 @@ void main() {
2870
3435
 
2871
3436
  fragColor = mix(mix(v00, v10, fx), mix(v01, v11, fx), fy);
2872
3437
  }
2873
- \`;var Ie=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Wr);let a=e.c/4,n=o.outW*a,u=this.makeTexture(null,n,o.outH);this.output={h:o.outH,w:o.outW,c:e.c,texture:u,texW:n,texH:o.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:o.outW,u_out_h:o.outH,u_c_groups:a},this.defaultSetup(),this.dispatch=[n,o.outH]}};var Pr=\`#version 300 es
3438
+ \`;var Ye=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Jr);let o=e.c/4,n=i.outW*o,s=this.makeTexture(null,n,i.outH);this.output={h:i.outH,w:i.outW,c:e.c,texture:s,texW:n,texH:i.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:i.outW,u_out_h:i.outH,u_c_groups:o},this.defaultSetup(),this.dispatch=[n,i.outH]}};var Zr=\`#version 300 es
3439
+ // Top-left crop: the output viewport is smaller than the input texture, so reading
3440
+ // the same fragment coord yields the top-left subregion (channel groups packed in
3441
+ // the x axis line up because group count is unchanged).
3442
+
3443
+ precision highp float;
3444
+ precision highp int;
3445
+
3446
+ uniform sampler2D u_input;
3447
+ out vec4 fragColor;
3448
+
3449
+ void main() {
3450
+ fragColor = texelFetch(u_input, ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)), 0);
3451
+ }
3452
+ \`;var Qe=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",Zr);let o=e.c/4,n=i.outW*o,s=this.makeTexture(null,n,i.outH);this.output={h:i.outH,w:i.outW,c:e.c,texture:s,texW:n,texH:i.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.defaultSetup(),this.dispatch=[n,i.outH]}};var eo=\`#version 300 es
2874
3453
  // Bicubic upsample (arbitrary scale) \\u2014 Keys cubic, a=-0.75 (PyTorch default
2875
3454
  // for mode='bicubic', align_corners=False).
2876
3455
  //
@@ -2930,7 +3509,7 @@ void main() {
2930
3509
  }
2931
3510
  fragColor = acc;
2932
3511
  }
2933
- \`;var De=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Pr);let a=e.c/4,n=o.outW*a,u=this.makeTexture(null,n,o.outH);this.output={h:o.outH,w:o.outW,c:e.c,texture:u,texW:n,texH:o.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:o.outW,u_out_h:o.outH,u_c_groups:a},this.defaultSetup(),this.dispatch=[n,o.outH]}};var Gr=\`#version 300 es
3512
+ \`;var Je=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",eo);let o=e.c/4,n=i.outW*o,s=this.makeTexture(null,n,i.outH);this.output={h:i.outH,w:i.outW,c:e.c,texture:s,texW:n,texH:i.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:i.outW,u_out_h:i.outH,u_c_groups:o},this.defaultSetup(),this.dispatch=[n,i.outH]}};var to=\`#version 300 es
2934
3513
  // Channel concat \\u2014 concatenates two NHWC textures along the channel dimension.
2935
3514
  // Both inputs must share the same spatial dimensions (W, H). Channel counts are
2936
3515
  // multiples of 4 so each "group" is one vec4 texel.
@@ -2963,7 +3542,7 @@ void main() {
2963
3542
  fragColor = texelFetch(u_input_b, ivec2(x_spatial * u_b_c_groups + c_b, y), 0);
2964
3543
  }
2965
3544
  }
2966
- \`;var Ae=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Gr);let a=e.c/4,n=o.c/4,u=a+n,p=e.c+o.c,l=e.w*u,c=this.makeTexture(null,l,e.h);this.output={h:e.h,w:e.w,c:p,texture:c,texW:l,texH:e.h},this.inputs=[e,o],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:o.texture}],this.uniformInts={u_a_c_groups:a,u_b_c_groups:n},this.defaultSetup(),this.dispatch=[l,e.h]}};var Br=\`#version 300 es
3545
+ \`;var Ze=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",to);let o=e.c/4,n=i.c/4,s=o+n,p=e.c+i.c,l=e.w*s,c=this.makeTexture(null,l,e.h);this.output={h:e.h,w:e.w,c:p,texture:c,texW:l,texH:e.h},this.inputs=[e,i],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:i.texture}],this.uniformInts={u_a_c_groups:o,u_b_c_groups:n},this.defaultSetup(),this.dispatch=[l,e.h]}};var ro=\`#version 300 es
2967
3546
  // Bilinear upsample + sigmoid fused \\u2014 sigmoid applied at write time, no intermediate buffer.
2968
3547
  // See bilinear_upsample.glsl for the manual 4-tap blend rationale.
2969
3548
  //
@@ -3013,7 +3592,7 @@ void main() {
3013
3592
  vec4 result = mix(mix(v00, v10, fx), mix(v01, v11, fx), fy);
3014
3593
  fragColor = 1.0 / (1.0 + exp(-result));
3015
3594
  }
3016
- \`;var Re=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Br);let a=e.c/4,n=o.outW*a,u=this.makeTexture(null,n,o.outH);this.output={h:o.outH,w:o.outW,c:e.c,texture:u,texW:n,texH:o.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:o.outW,u_out_h:o.outH,u_c_groups:a},this.defaultSetup(),this.dispatch=[n,o.outH]}};var Ur=\`#version 300 es
3595
+ \`;var et=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",ro);let o=e.c/4,n=i.outW*o,s=this.makeTexture(null,n,i.outH);this.output={h:i.outH,w:i.outW,c:e.c,texture:s,texW:n,texH:i.outH},this.inputs=[e],this.samplers=[{name:"u_input",texture:e.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:i.outW,u_out_h:i.outH,u_c_groups:o},this.defaultSetup(),this.dispatch=[n,i.outH]}};var oo=\`#version 300 es
3017
3596
  // Bilinear upsample (input_a) + channel concat (with input_b) fused.
3018
3597
  // input_a is the decoder tensor at small spatial res (in_h \\xD7 in_w), bilinearly resized to (out_h \\xD7 out_w).
3019
3598
  // input_b is the encoder skip feature already at output resolution.
@@ -3071,7 +3650,7 @@ void main() {
3071
3650
  fragColor = texelFetch(u_input_b, ivec2(x_out * u_b_c_groups + c_b, y_out), 0);
3072
3651
  }
3073
3652
  }
3074
- \`;var Me=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights",[]);i(this,"output");i(this,"dispatch");i(this,"shader",Ur);let n=e.c/4,u=o.c/4,p=n+u,l=e.c+o.c,c=a.outW*p,m=this.makeTexture(null,c,a.outH);this.output={h:a.outH,w:a.outW,c:l,texture:m,texW:c,texH:a.outH},this.inputs=[e,o],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:o.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:a.outW,u_out_h:a.outH,u_a_c_groups:n,u_b_c_groups:u},this.defaultSetup(),this.dispatch=[c,a.outH]}};var Sr=\`#version 300 es
3653
+ \`;var tt=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights",[]);a(this,"output");a(this,"dispatch");a(this,"shader",oo);let n=e.c/4,s=i.c/4,p=n+s,l=e.c+i.c,c=o.outW*p,d=this.makeTexture(null,c,o.outH);this.output={h:o.outH,w:o.outW,c:l,texture:d,texW:c,texH:o.outH},this.inputs=[e,i],this.samplers=[{name:"u_input_a",texture:e.texture},{name:"u_input_b",texture:i.texture}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:o.outW,u_out_h:o.outH,u_a_c_groups:n,u_b_c_groups:s},this.defaultSetup(),this.dispatch=[c,o.outH]}};var io=\`#version 300 es
3075
3654
  // Bilinear upsample + 1\\xD71 pointwise conv fused.
3076
3655
  // For each output pixel + out group, bilinearly samples each in_group from input,
3077
3656
  // applies the 1\\xD71 conv weight, and writes the activated result.
@@ -3148,7 +3727,7 @@ void main() {
3148
3727
 
3149
3728
  fragColor = result;
3150
3729
  }
3151
- \`;var He=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Sr);let n=e.c/4,u=a.outChannels/4,p=d(o.weights),l=d(o.bias),c=this.makeTexture(p,n*4,u),m=this.makeTexture(l,u,1),_=a.outW*u,g=this.makeTexture(null,_,a.outH);this.output={h:a.outH,w:a.outW,c:a.outChannels,texture:g,texW:_,texH:a.outH},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:c},{name:"u_bias",texture:m}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:a.outW,u_out_h:a.outH,u_in_c_groups:n,u_out_c_groups:u,u_activation:a.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[_,a.outH]}};var Lr=\`#version 300 es
3730
+ \`;var rt=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",io);let n=e.c/4,s=o.outChannels/4,p=m(i.weights),l=m(i.bias),c=this.makeTexture(p,n*4,s),d=this.makeTexture(l,s,1),_=o.outW*s,b=this.makeTexture(null,_,o.outH);this.output={h:o.outH,w:o.outW,c:o.outChannels,texture:b,texW:_,texH:o.outH},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:c},{name:"u_bias",texture:d}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_out_w:o.outW,u_out_h:o.outH,u_in_c_groups:n,u_out_c_groups:s,u_activation:o.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[_,o.outH]}};var ao=\`#version 300 es
3152
3731
  // Conv2d + skip add fused \\u2014 identical to conv2d.glsl with a skip texture added at write time.
3153
3732
  // See conv2d.glsl for tensor/weight layout details.
3154
3733
 
@@ -3212,7 +3791,7 @@ void main() {
3212
3791
 
3213
3792
  fragColor = result + texelFetch(u_skip, ivec2(fx, fy), 0);
3214
3793
  }
3215
- \`;var ze=class extends h{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Lr);let u=w(e.h,n.kernel,n.stride,n.padding),p=w(e.w,n.kernel,n.stride,n.padding),l=e.c/4,c=n.outChannels/4,m=k(n.padding,e.h,u,n.kernel,n.stride),_=k(n.padding,e.w,p,n.kernel,n.stride),g=d(a.weights),x=d(a.bias),y=this.makeTexture(g,l*4,n.kernel*n.kernel*c),T=this.makeTexture(x,c,1),P=p*c,z=this.makeTexture(null,P,u);this.output={h:u,w:p,c:n.outChannels,texture:z,texW:P,texH:u},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_skip",texture:o.texture},{name:"u_weights",texture:y},{name:"u_bias",texture:T}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_in_c_groups:l,u_out_c_groups:c,u_kernel_h:n.kernel,u_kernel_w:n.kernel,u_stride:n.stride,u_pad_top:m,u_pad_left:_,u_activation:n.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[P,u]}};var Fr=\`#version 300 es
3794
+ \`;var ot=class extends h{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",ao);let s=T(e.h,n.kernel,n.stride,n.padding),p=T(e.w,n.kernel,n.stride,n.padding),l=e.c/4,c=n.outChannels/4,d=C(n.padding,e.h,s,n.kernel,n.stride),_=C(n.padding,e.w,p,n.kernel,n.stride),b=m(o.weights),g=m(o.bias),v=this.makeTexture(b,l*4,n.kernel*n.kernel*c),x=this.makeTexture(g,c,1),k=p*c,B=this.makeTexture(null,k,s);this.output={h:s,w:p,c:n.outChannels,texture:B,texW:k,texH:s},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_skip",texture:i.texture},{name:"u_weights",texture:v},{name:"u_bias",texture:x}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_in_c_groups:l,u_out_c_groups:c,u_kernel_h:n.kernel,u_kernel_w:n.kernel,u_stride:n.stride,u_pad_top:d,u_pad_left:_,u_activation:n.activation==="relu6"?1:0},this.defaultSetup(),this.dispatch=[k,s]}};var no=\`#version 300 es
3216
3795
  // proj_residual: bespoke 1\\xD71 conv (no activation) + residual add, fused.
3217
3796
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation. Both
3218
3797
  // inputs share the same spatial resolution. See conv2d.glsl for the weight
@@ -3254,7 +3833,7 @@ void main() {
3254
3833
 
3255
3834
  fragColor = result + texelFetch(u_skip, ivec2(fx, fy), 0);
3256
3835
  }
3257
- \`;var Ve=class extends h{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Fr);let u=e.c/4,p=n.outChannels/4,l=d(a.weights),c=d(a.bias),m=this.makeTexture(l,u*4,p),_=this.makeTexture(c,p,1),g=e.w*p,x=this.makeTexture(null,g,e.h);this.output={h:e.h,w:e.w,c:n.outChannels,texture:x,texW:g,texH:e.h},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_skip",texture:o.texture},{name:"u_weights",texture:m},{name:"u_bias",texture:_}],this.uniformInts={u_in_c_groups:u,u_out_c_groups:p},this.defaultSetup(),this.dispatch=[g,e.h]}};var Er=\`#version 300 es
3836
+ \`;var it=class extends h{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",no);let s=e.c/4,p=n.outChannels/4,l=m(o.weights),c=m(o.bias),d=this.makeTexture(l,s*4,p),_=this.makeTexture(c,p,1),b=e.w*p,g=this.makeTexture(null,b,e.h);this.output={h:e.h,w:e.w,c:n.outChannels,texture:g,texW:b,texH:e.h},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_skip",texture:i.texture},{name:"u_weights",texture:d},{name:"u_bias",texture:_}],this.uniformInts={u_in_c_groups:s,u_out_c_groups:p},this.defaultSetup(),this.dispatch=[b,e.h]}};var so=\`#version 300 es
3258
3837
  // concat_conv2d: fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one pass.
3259
3838
  // Both inputs already at output resolution. Weight cols [0, a_groups) read a,
3260
3839
  // [a_groups, I) read b. Weight texture layout matches conv2d.glsl
@@ -3315,7 +3894,7 @@ void main() {
3315
3894
 
3316
3895
  fragColor = clamp(result, 0.0, 6.0);
3317
3896
  }
3318
- \`;var Ne=class extends h{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Er);let u=e.c/4,p=o.c/4,l=u+p,c=n.outChannels/4,m=d(a.weights),_=d(a.bias),g=this.makeTexture(m,l*4,9*c),x=this.makeTexture(_,c,1),y=e.w*c,T=this.makeTexture(null,y,e.h);this.output={h:e.h,w:e.w,c:n.outChannels,texture:T,texW:y,texH:e.h},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_a",texture:e.texture},{name:"u_b",texture:o.texture},{name:"u_weights",texture:g},{name:"u_bias",texture:x}],this.uniformInts={u_w:e.w,u_h:e.h,u_a_groups:u,u_b_groups:p,u_out_c_groups:c},this.defaultSetup(),this.dispatch=[y,e.h]}};var Or=\`#version 300 es
3897
+ \`;var at=class extends h{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",so);let s=e.c/4,p=i.c/4,l=s+p,c=n.outChannels/4,d=m(o.weights),_=m(o.bias),b=this.makeTexture(d,l*4,9*c),g=this.makeTexture(_,c,1),v=e.w*c,x=this.makeTexture(null,v,e.h);this.output={h:e.h,w:e.w,c:n.outChannels,texture:x,texW:v,texH:e.h},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_a",texture:e.texture},{name:"u_b",texture:i.texture},{name:"u_weights",texture:b},{name:"u_bias",texture:g}],this.uniformInts={u_w:e.w,u_h:e.h,u_a_groups:s,u_b_groups:p,u_out_c_groups:c},this.defaultSetup(),this.dispatch=[v,e.h]}};var uo=\`#version 300 es
3319
3898
  // gates_fused: ConvGRU z + r gates, fused. Production config (c_up=2,
3320
3899
  // recurrent=1). u_in (.x=a, .y=b), h_prev (.x). weights 9 vec4 =
3321
3900
  // (z_w_b, z_w_h, r_w_b, r_w_h) in a (9,1) texture. bias .xy. output (z, r, 0, 0).
@@ -3358,7 +3937,7 @@ void main() {
3358
3937
  float r = 1.0 / (1.0 + exp(-r_pre));
3359
3938
  fragColor = vec4(z, r, 0.0, 0.0);
3360
3939
  }
3361
- \`;var $e=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Or);let n=this.makeTexture(d(a.weights),9,1),u=this.makeTexture(b(a.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_h_prev",texture:o.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:u}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var Ir=\`#version 300 es
3940
+ \`;var nt=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",uo);let n=this.makeTexture(m(o.weights),9,1),s=this.makeTexture(y(o.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_h_prev",texture:i.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:s}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var po=\`#version 300 es
3362
3941
  // cand_update_fused: ConvGRU candidate + state update + output, fused.
3363
3942
  // Production config (c_up=2, recurrent=1). u_in (.x=a, .y=b), h_prev (.x),
3364
3943
  // gates_out (.x=z, .y=r). weights 9 vec4 (.xy = b_w, rh_w) in a (9,1) texture.
@@ -3406,7 +3985,7 @@ void main() {
3406
3985
  float b_out = u_cur.y + gamma * h_new;
3407
3986
  fragColor = vec4(u_cur.x, b_out, h_new, 0.0);
3408
3987
  }
3409
- \`;var Xe=class extends h{constructor(r,e,o,a,n,u){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Ir);let p=this.makeTexture(d(n.weights),9,1),l=this.makeTexture(b(n.bias),1,1),c=this.makeTexture(b(u),1,1),m=e.w,_=this.makeTexture(null,m,e.h);this.output={h:e.h,w:e.w,c:4,texture:_,texW:m,texH:e.h},this.inputs=[e,o,a],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_h_prev",texture:o.texture},{name:"u_gates_out",texture:a.texture},{name:"u_weights",texture:p},{name:"u_bias",texture:l},{name:"u_gamma",texture:c}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[m,e.h]}};var Dr=\`#version 300 es
3988
+ \`;var st=class extends h{constructor(r,e,i,o,n,s){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",po);let p=this.makeTexture(m(n.weights),9,1),l=this.makeTexture(y(n.bias),1,1),c=this.makeTexture(y(s),1,1),d=e.w,_=this.makeTexture(null,d,e.h);this.output={h:e.h,w:e.w,c:4,texture:_,texW:d,texH:e.h},this.inputs=[e,i,o],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_h_prev",texture:i.texture},{name:"u_gates_out",texture:o.texture},{name:"u_weights",texture:p},{name:"u_bias",texture:l},{name:"u_gamma",texture:c}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[d,e.h]}};var lo=\`#version 300 es
3410
3989
  // conv_expand: bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
3411
3990
  // Input N ch (in_groups vec4); output 2ch in .xy (.zw = 0). Weights: 9 *
3412
3991
  // in_groups mat4x2 (8 floats each, col-major c0r0,c0r1,...,c3r0,c3r1) in a
@@ -3449,7 +4028,7 @@ void main() {
3449
4028
 
3450
4029
  fragColor = vec4(max(result, vec2(0.0)), 0.0, 0.0); // expand_feat is F.relu
3451
4030
  }
3452
- \`;var je=class extends h{constructor(r,e,o){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Dr);let a=e.c/4,n=this.makeTexture(d(o.weights),18*a,1),u=this.makeTexture(b(o.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:u}],this.uniformInts={u_w:e.w,u_h:e.h,u_in_groups:a},this.defaultSetup(),this.dispatch=[p,e.h]}};var Ar=\`#version 300 es
4031
+ \`;var ut=class extends h{constructor(r,e,i){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",lo);let o=e.c/4,n=this.makeTexture(m(i.weights),18*o,1),s=this.makeTexture(y(i.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:s}],this.uniformInts={u_w:e.w,u_h:e.h,u_in_groups:o},this.defaultSetup(),this.dispatch=[p,e.h]}};var co=\`#version 300 es
3453
4032
  // cat_conv_6to2: fused concat(u[2], d[4]) \\u2192 6\\u21922 conv 3\\xD73 (pad 1) + relu
3454
4033
  // (E up1_combine). Channel order v3a=(u.x,u.y,d.x), v3b=d.yzw. weights = 9*2
3455
4034
  // mat3x2 (6 floats each, col-major) in a 1-row (27-texel) texture.
@@ -3496,7 +4075,7 @@ void main() {
3496
4075
 
3497
4076
  fragColor = vec4(max(result, vec2(0.0)), 0.0, 0.0); // up1_combine is F.relu
3498
4077
  }
3499
- \`;var qe=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Ar);let n=this.makeTexture(d(a.weights),27,1),u=this.makeTexture(b(a.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_d_in",texture:o.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:u}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var Rr=\`#version 300 es
4078
+ \`;var pt=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",co);let n=this.makeTexture(m(o.weights),27,1),s=this.makeTexture(y(o.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_u_in",texture:e.texture},{name:"u_d_in",texture:i.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:s}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var mo=\`#version 300 es
3500
4079
  // down_adapter: stride-N 3\\xD73 conv (mat4x4, 4\\u21924) + relu, then 1\\xD71 adapter
3501
4080
  // (4\\u21923, last row 0). down_w = 9 mat4x4 (1-row, 36 texels); adapt_w = 1 mat4x4
3502
4081
  // (4 texels). Output 3ch in .xyz (.w=0). Symmetric pad. Weight packing matches
@@ -3548,7 +4127,7 @@ void main() {
3548
4127
  a.z = awf(2) * d.x + awf(6) * d.y + awf(10) * d.z + awf(14) * d.w + ab.z;
3549
4128
  fragColor = vec4(a.xyz, 0.0);
3550
4129
  }
3551
- \`;var Ke=class extends h{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Rr);let u=w(e.h,3,n.stride,1),p=w(e.w,3,n.stride,1),l=k(1,e.h,u,3,n.stride),c=this.makeTexture(d(o.weights),36,1),m=this.makeTexture(b(o.bias),1,1),_=this.makeTexture(d(a.weights),4,1),g=this.makeTexture(b(a.bias),1,1),x=p,y=this.makeTexture(null,x,u);this.output={h:u,w:p,c:4,texture:y,texW:x,texH:u},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_down_w",texture:c},{name:"u_down_b",texture:m},{name:"u_adapt_w",texture:_},{name:"u_adapt_b",texture:g}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_stride:n.stride,u_pad:l},this.defaultSetup(),this.dispatch=[x,u]}};var Mr=\`#version 300 es
4130
+ \`;var lt=class extends h{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",mo);let s=T(e.h,3,n.stride,1),p=T(e.w,3,n.stride,1),l=C(1,e.h,s,3,n.stride),c=this.makeTexture(m(i.weights),36,1),d=this.makeTexture(y(i.bias),1,1),_=this.makeTexture(m(o.weights),4,1),b=this.makeTexture(y(o.bias),1,1),g=p,v=this.makeTexture(null,g,s);this.output={h:s,w:p,c:4,texture:v,texW:g,texH:s},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_down_w",texture:c},{name:"u_down_b",texture:d},{name:"u_adapt_w",texture:_},{name:"u_adapt_b",texture:b}],this.uniformInts={u_in_w:e.w,u_in_h:e.h,u_stride:n.stride,u_pad:l},this.defaultSetup(),this.dispatch=[g,s]}};var fo=\`#version 300 es
3552
4131
  // up_final: cat(u[2], rgb[3]) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
3553
4132
  // weights 18 vec4 (1-row): [kpos]=(w0,w1,0,0) for u, [9+kpos]=(w2,w3,w4,0) rgb.
3554
4133
 
@@ -3586,7 +4165,7 @@ void main() {
3586
4165
 
3587
4166
  fragColor = vec4(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
3588
4167
  }
3589
- \`;var Ye=class extends h{constructor(r,e,o,a){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Mr);let n=this.makeTexture(d(a.weights),18,1),u=this.makeTexture(b(a.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,o],this.weights=[],this.samplers=[{name:"u_u_gru",texture:e.texture},{name:"u_rgb",texture:o.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:u}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var Hr=\`#version 300 es
4168
+ \`;var ct=class extends h{constructor(r,e,i,o){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",fo);let n=this.makeTexture(m(o.weights),18,1),s=this.makeTexture(y(o.bias),1,1),p=e.w,l=this.makeTexture(null,p,e.h);this.output={h:e.h,w:e.w,c:4,texture:l,texW:p,texH:e.h},this.inputs=[e,i],this.weights=[],this.samplers=[{name:"u_u_gru",texture:e.texture},{name:"u_rgb",texture:i.texture},{name:"u_weights",texture:n},{name:"u_bias",texture:s}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[p,e.h]}};var ho=\`#version 300 es
3590
4169
  // up_final_skip (C/D alpha head): cat(u[2], d_full[4], rgb[3]) \\u2192 conv 9\\u21921 \\u2192
3591
4170
  // sigmoid. Weights = 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u;
3592
4171
  // [kpos*3+1]=(w2..w5) d_full; [kpos*3+2]=(w6,w7,w8,0) rgb.
@@ -3629,7 +4208,7 @@ void main() {
3629
4208
 
3630
4209
  fragColor = vec4(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
3631
4210
  }
3632
- \`;var Qe=class extends h{constructor(r,e,o,a,n){super(r);i(this,"inputs");i(this,"weights");i(this,"output");i(this,"dispatch");i(this,"shader",Hr);let u=this.makeTexture(d(n.weights),27,1),p=this.makeTexture(b(n.bias),1,1),l=e.w,c=this.makeTexture(null,l,e.h);this.output={h:e.h,w:e.w,c:4,texture:c,texW:l,texH:e.h},this.inputs=[e,o,a],this.weights=[],this.samplers=[{name:"u_u_gru",texture:e.texture},{name:"u_d_full",texture:o.texture},{name:"u_rgb",texture:a.texture},{name:"u_weights",texture:u},{name:"u_bias",texture:p}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[l,e.h]}};var zr=\`#version 300 es
4211
+ \`;var dt=class extends h{constructor(r,e,i,o,n){super(r);a(this,"inputs");a(this,"weights");a(this,"output");a(this,"dispatch");a(this,"shader",ho);let s=this.makeTexture(m(n.weights),27,1),p=this.makeTexture(y(n.bias),1,1),l=e.w,c=this.makeTexture(null,l,e.h);this.output={h:e.h,w:e.w,c:4,texture:c,texW:l,texH:e.h},this.inputs=[e,i,o],this.weights=[],this.samplers=[{name:"u_u_gru",texture:e.texture},{name:"u_d_full",texture:i.texture},{name:"u_rgb",texture:o.texture},{name:"u_weights",texture:s},{name:"u_bias",texture:p}],this.uniformInts={u_w:e.w,u_h:e.h},this.defaultSetup(),this.dispatch=[l,e.h]}};var _o=\`#version 300 es
3633
4212
  // Composite an RGBA image over a solid background color, gated by a
3634
4213
  // 1-channel alpha mask. Output: premultiplied RGBA.
3635
4214
  //
@@ -3660,12 +4239,12 @@ void main() {
3660
4239
  vec3 rgb = fg * a + u_bgColor * (1.0 - a);
3661
4240
  fragColor = vec4(rgb, 1.0);
3662
4241
  }
3663
- \`;var ji=\`#version 300 es
4242
+ \`;var Da=\`#version 300 es
3664
4243
  const vec2 VERTS[6] = vec2[6](
3665
4244
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3666
4245
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3667
4246
  );
3668
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,Je=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"program");i(this,"imageTex");i(this,"alphaTex");i(this,"bgColor");if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeSolid: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match. Run the upscaler first.\`);let a=r,n=e;this.imageTex=a.texture,this.alphaTex=n.texture,this.bgColor=o;let u=t.gl,p=u.createShader(u.VERTEX_SHADER);u.shaderSource(p,ji),u.compileShader(p);let l=u.createShader(u.FRAGMENT_SHADER);if(u.shaderSource(l,zr),u.compileShader(l),!u.getShaderParameter(l,u.COMPILE_STATUS))throw new Error(\`composite_solid GLSL compile error: \${u.getShaderInfoLog(l)}\`);if(this.program=u.createProgram(),u.attachShader(this.program,p),u.attachShader(this.program,l),u.linkProgram(this.program),!u.getProgramParameter(this.program,u.LINK_STATUS))throw new Error(\`composite_solid GLSL link error: \${u.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.uniform3f(t.getUniformLocation(this.program,"u_bgColor"),this.bgColor[0],this.bgColor[1],this.bgColor[2]),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var Vr=\`#version 300 es
4247
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,mt=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"program");a(this,"imageTex");a(this,"alphaTex");a(this,"bgColor");if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeSolid: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match. Run the upscaler first.\`);let o=r,n=e;this.imageTex=o.texture,this.alphaTex=n.texture,this.bgColor=i;let s=t.gl,p=s.createShader(s.VERTEX_SHADER);s.shaderSource(p,Da),s.compileShader(p);let l=s.createShader(s.FRAGMENT_SHADER);if(s.shaderSource(l,_o),s.compileShader(l),!s.getShaderParameter(l,s.COMPILE_STATUS))throw new Error(\`composite_solid GLSL compile error: \${s.getShaderInfoLog(l)}\`);if(this.program=s.createProgram(),s.attachShader(this.program,p),s.attachShader(this.program,l),s.linkProgram(this.program),!s.getProgramParameter(this.program,s.LINK_STATUS))throw new Error(\`composite_solid GLSL link error: \${s.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.uniform3f(t.getUniformLocation(this.program,"u_bgColor"),this.bgColor[0],this.bgColor[1],this.bgColor[2]),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var go=\`#version 300 es
3669
4248
  // Same as composite_solid but bg is a texture (NHWC vec4 tensor) instead of
3670
4249
  // a uniform color. Caller invariants: image, alpha, bg all share h \\xD7 w, and
3671
4250
  // canvas dimensions match.
@@ -3691,12 +4270,12 @@ void main() {
3691
4270
  vec3 rgb = fg * a + bg * (1.0 - a);
3692
4271
  fragColor = vec4(rgb, 1.0);
3693
4272
  }
3694
- \`;var Ki=\`#version 300 es
4273
+ \`;var Ia=\`#version 300 es
3695
4274
  const vec2 VERTS[6] = vec2[6](
3696
4275
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3697
4276
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3698
4277
  );
3699
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,Ze=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"program");i(this,"imageTex");i(this,"alphaTex");i(this,"bgTex");if(r.h!==e.h||r.w!==e.w||r.h!==o.h||r.w!==o.w)throw new Error(\`CompositeImage: image (\${r.h}\\xD7\${r.w}), alpha (\${e.h}\\xD7\${e.w}), and bg (\${o.h}\\xD7\${o.w}) must all match. Run upscaler / resizer first.\`);this.imageTex=r.texture,this.alphaTex=e.texture,this.bgTex=o.texture;let a=t.gl,n=a.createShader(a.VERTEX_SHADER);a.shaderSource(n,Ki),a.compileShader(n);let u=a.createShader(a.FRAGMENT_SHADER);if(a.shaderSource(u,Vr),a.compileShader(u),!a.getShaderParameter(u,a.COMPILE_STATUS))throw new Error(\`composite_image GLSL compile error: \${a.getShaderInfoLog(u)}\`);if(this.program=a.createProgram(),a.attachShader(this.program,n),a.attachShader(this.program,u),a.linkProgram(this.program),!a.getProgramParameter(this.program,a.LINK_STATUS))throw new Error(\`composite_image GLSL link error: \${a.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.bgTex),t.uniform1i(t.getUniformLocation(this.program,"u_bg"),2),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var Nr=\`#version 300 es
4278
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,ft=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"program");a(this,"imageTex");a(this,"alphaTex");a(this,"bgTex");if(r.h!==e.h||r.w!==e.w||r.h!==i.h||r.w!==i.w)throw new Error(\`CompositeImage: image (\${r.h}\\xD7\${r.w}), alpha (\${e.h}\\xD7\${e.w}), and bg (\${i.h}\\xD7\${i.w}) must all match. Run upscaler / resizer first.\`);this.imageTex=r.texture,this.alphaTex=e.texture,this.bgTex=i.texture;let o=t.gl,n=o.createShader(o.VERTEX_SHADER);o.shaderSource(n,Ia),o.compileShader(n);let s=o.createShader(o.FRAGMENT_SHADER);if(o.shaderSource(s,go),o.compileShader(s),!o.getShaderParameter(s,o.COMPILE_STATUS))throw new Error(\`composite_image GLSL compile error: \${o.getShaderInfoLog(s)}\`);if(this.program=o.createProgram(),o.attachShader(this.program,n),o.attachShader(this.program,s),o.linkProgram(this.program),!o.getProgramParameter(this.program,o.LINK_STATUS))throw new Error(\`composite_image GLSL link error: \${o.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.bgTex),t.uniform1i(t.getUniformLocation(this.program,"u_bg"),2),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var bo=\`#version 300 es
3700
4279
  // Like composite_image but bg is bilinearly sampled \\u2014 bg is at a smaller
3701
4280
  // resolution than (image, alpha) at canvas h \\xD7 w. Used by CompositorBlur to
3702
4281
  // skip the final full-res upsample in the blur pyramid.
@@ -3745,12 +4324,12 @@ void main() {
3745
4324
  vec3 rgb = fg * a + bg * (1.0 - a);
3746
4325
  fragColor = vec4(rgb, 1.0);
3747
4326
  }
3748
- \`;var Qi=\`#version 300 es
4327
+ \`;var Ma=\`#version 300 es
3749
4328
  const vec2 VERTS[6] = vec2[6](
3750
4329
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3751
4330
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3752
4331
  );
3753
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,et=class{constructor(t,r,e,o){i(this,"backend",t);i(this,"program");i(this,"imageTex");i(this,"alphaTex");i(this,"bgTex");i(this,"outW");i(this,"outH");i(this,"bgW");i(this,"bgH");if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeImageBilinear: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match.\`);this.imageTex=r.texture,this.alphaTex=e.texture,this.bgTex=o.texture,this.outW=r.w,this.outH=r.h,this.bgW=o.w,this.bgH=o.h;let a=t.gl,n=a.createShader(a.VERTEX_SHADER);a.shaderSource(n,Qi),a.compileShader(n);let u=a.createShader(a.FRAGMENT_SHADER);if(a.shaderSource(u,Nr),a.compileShader(u),!a.getShaderParameter(u,a.COMPILE_STATUS))throw new Error(\`composite_image_bilinear GLSL compile error: \${a.getShaderInfoLog(u)}\`);if(this.program=a.createProgram(),a.attachShader(this.program,n),a.attachShader(this.program,u),a.linkProgram(this.program),!a.getProgramParameter(this.program,a.LINK_STATUS))throw new Error(\`composite_image_bilinear GLSL link error: \${a.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.bgTex),t.uniform1i(t.getUniformLocation(this.program,"u_bg"),2),t.uniform1i(t.getUniformLocation(this.program,"u_out_w"),this.outW),t.uniform1i(t.getUniformLocation(this.program,"u_out_h"),this.outH),t.uniform1i(t.getUniformLocation(this.program,"u_bg_w"),this.bgW),t.uniform1i(t.getUniformLocation(this.program,"u_bg_h"),this.bgH),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var $r=\`#version 300 es
4332
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,ht=class{constructor(t,r,e,i){a(this,"backend",t);a(this,"program");a(this,"imageTex");a(this,"alphaTex");a(this,"bgTex");a(this,"outW");a(this,"outH");a(this,"bgW");a(this,"bgH");if(r.h!==e.h||r.w!==e.w)throw new Error(\`CompositeImageBilinear: image (\${r.h}\\xD7\${r.w}) and alpha (\${e.h}\\xD7\${e.w}) must match.\`);this.imageTex=r.texture,this.alphaTex=e.texture,this.bgTex=i.texture,this.outW=r.w,this.outH=r.h,this.bgW=i.w,this.bgH=i.h;let o=t.gl,n=o.createShader(o.VERTEX_SHADER);o.shaderSource(n,Ma),o.compileShader(n);let s=o.createShader(o.FRAGMENT_SHADER);if(o.shaderSource(s,bo),o.compileShader(s),!o.getShaderParameter(s,o.COMPILE_STATUS))throw new Error(\`composite_image_bilinear GLSL compile error: \${o.getShaderInfoLog(s)}\`);if(this.program=o.createProgram(),o.attachShader(this.program,n),o.attachShader(this.program,s),o.linkProgram(this.program),!o.getProgramParameter(this.program,o.LINK_STATUS))throw new Error(\`composite_image_bilinear GLSL link error: \${o.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.alphaTex),t.uniform1i(t.getUniformLocation(this.program,"u_alpha"),1),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.bgTex),t.uniform1i(t.getUniformLocation(this.program,"u_bg"),2),t.uniform1i(t.getUniformLocation(this.program,"u_out_w"),this.outW),t.uniform1i(t.getUniformLocation(this.program,"u_out_h"),this.outH),t.uniform1i(t.getUniformLocation(this.program,"u_bg_w"),this.bgW),t.uniform1i(t.getUniformLocation(this.program,"u_bg_h"),this.bgH),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var vo=\`#version 300 es
3754
4333
  // Passthrough "compositor": writes the image directly to the canvas
3755
4334
  // (default framebuffer). No alpha math, no background. Used by RenderOp
3756
4335
  // when the renderer is in disabled state.
@@ -3773,12 +4352,12 @@ void main() {
3773
4352
  vec3 rgb = texelFetch(u_image, px, 0).rgb;
3774
4353
  fragColor = vec4(rgb, 1.0);
3775
4354
  }
3776
- \`;var Zi=\`#version 300 es
4355
+ \`;var Ha=\`#version 300 es
3777
4356
  const vec2 VERTS[6] = vec2[6](
3778
4357
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3779
4358
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3780
4359
  );
3781
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,tt=class{constructor(t,r){i(this,"backend",t);i(this,"program");i(this,"imageTex");this.imageTex=r.texture;let e=t.gl,o=e.createShader(e.VERTEX_SHADER);e.shaderSource(o,Zi),e.compileShader(o);let a=e.createShader(e.FRAGMENT_SHADER);if(e.shaderSource(a,$r),e.compileShader(a),!e.getShaderParameter(a,e.COMPILE_STATUS))throw new Error(\`composite_passthrough GLSL compile error: \${e.getShaderInfoLog(a)}\`);if(this.program=e.createProgram(),e.attachShader(this.program,o),e.attachShader(this.program,a),e.linkProgram(this.program),!e.getProgramParameter(this.program,e.LINK_STATUS))throw new Error(\`composite_passthrough GLSL link error: \${e.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var Xr=\`#version 300 es
4360
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,_t=class{constructor(t,r){a(this,"backend",t);a(this,"program");a(this,"imageTex");this.imageTex=r.texture;let e=t.gl,i=e.createShader(e.VERTEX_SHADER);e.shaderSource(i,Ha),e.compileShader(i);let o=e.createShader(e.FRAGMENT_SHADER);if(e.shaderSource(o,vo),e.compileShader(o),!e.getShaderParameter(o,e.COMPILE_STATUS))throw new Error(\`composite_passthrough GLSL compile error: \${e.getShaderInfoLog(o)}\`);if(this.program=e.createProgram(),e.attachShader(this.program,i),e.attachShader(this.program,o),e.linkProgram(this.program),!e.getProgramParameter(this.program,e.LINK_STATUS))throw new Error(\`composite_passthrough GLSL link error: \${e.getProgramInfoLog(this.program)}\`)}run(){let t=this.backend.gl;t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.imageTex),t.uniform1i(t.getUniformLocation(this.program,"u_image"),0),this.backend.bindDisplayFramebuffer(),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var xo=\`#version 300 es
3782
4361
  precision highp float;
3783
4362
 
3784
4363
  // Input op \\u2014 bilinear-sample a source texture (RGBA8 unorm uploaded from an
@@ -3796,21 +4375,20 @@ void main() {
3796
4375
  vec2 uv = (gl_FragCoord.xy + vec2(0.5)) / vec2(float(u_out_w), float(u_out_h));
3797
4376
  fragColor = texture(u_src, uv);
3798
4377
  }
3799
- \`;var ta=\`#version 300 es
4378
+ \`;var Va=\`#version 300 es
3800
4379
  const vec2 VERTS[6] = vec2[6](
3801
4380
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3802
4381
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3803
4382
  );
3804
- void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,rt=class{constructor(t,r,e){i(this,"backend",t);i(this,"output");i(this,"gl");i(this,"program");i(this,"srcTex");i(this,"uOutW");i(this,"uOutH");i(this,"uSrc");i(this,"source",null);let o=t.gl;this.gl=o,this.output=t.tensor(r,e,4),this.srcTex=o.createTexture(),o.bindTexture(o.TEXTURE_2D,this.srcTex),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE);let a=o.createShader(o.VERTEX_SHADER);o.shaderSource(a,ta),o.compileShader(a);let n=o.createShader(o.FRAGMENT_SHADER);if(o.shaderSource(n,Xr),o.compileShader(n),!o.getShaderParameter(n,o.COMPILE_STATUS))throw new Error(\`Input GLSL compile error: \${o.getShaderInfoLog(n)}\`);if(this.program=o.createProgram(),o.attachShader(this.program,a),o.attachShader(this.program,n),o.linkProgram(this.program),!o.getProgramParameter(this.program,o.LINK_STATUS))throw new Error(\`Input GLSL link error: \${o.getProgramInfoLog(this.program)}\`);this.uSrc=o.getUniformLocation(this.program,"u_src"),this.uOutW=o.getUniformLocation(this.program,"u_out_w"),this.uOutH=o.getUniformLocation(this.program,"u_out_h")}setSource(t){this.source=t}run(){if(!this.source)throw new Error("InputWebGL.run() called before setSource()");let t=this.gl;t.bindTexture(t.TEXTURE_2D,this.srcTex),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.source),t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.srcTex),t.uniform1i(this.uSrc,0),t.uniform1i(this.uOutW,this.output.w),t.uniform1i(this.uOutH,this.output.h),t.bindFramebuffer(t.FRAMEBUFFER,this.backend.fbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.output.texture,0),t.viewport(0,0,this.output.texW,this.output.texH),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var L=class s{constructor(t,r,e){i(this,"gl",t);i(this,"canvas",r);i(this,"dtype",e);i(this,"ops");i(this,"presenters");i(this,"fbo");i(this,"textureFormat");this.fbo=t.createFramebuffer(),this.textureFormat=e==="f16"?{internalFormat:t.RGBA16F,format:t.RGBA,type:t.HALF_FLOAT,bytesPerElement:2}:{internalFormat:t.RGBA32F,format:t.RGBA,type:t.FLOAT,bytesPerElement:4},this.ops={Conv2d:(o,a,n)=>new Ue(this,o,a,n),DepthwiseConv2d:(o,a,n)=>new Se(this,o,a,n),Add:(o,a)=>new Le(this,o,a),Sigmoid:o=>new Fe(this,o),Tanh:o=>new Ee(this,o),ElementwiseMul:(o,a)=>new Oe(this,o,a),BilinearUpsample:(o,a)=>new Ie(this,o,a),BicubicUpsample:(o,a)=>new De(this,o,a),ChannelConcat:(o,a)=>new Ae(this,o,a),Conv2dAdd:(o,a,n,u)=>new ze(this,o,a,n,u),ProjResidual:(o,a,n,u)=>new Ve(this,o,a,n,u),ConcatConv2d:(o,a,n,u)=>new Ne(this,o,a,n,u),GatesFused:(o,a,n)=>new $e(this,o,a,n),CandUpdateFused:(o,a,n,u,p)=>new Xe(this,o,a,n,u,p),ConvExpand:(o,a)=>new je(this,o,a),CatConv6to2:(o,a,n)=>new qe(this,o,a,n),DownAdapter:(o,a,n,u)=>new Ke(this,o,a,n,u),UpFinal:(o,a,n)=>new Ye(this,o,a,n),UpFinalSkip:(o,a,n,u)=>new Qe(this,o,a,n,u),UpsampleConcat:(o,a,n)=>new Me(this,o,a,n),UpsampleConv1x1:(o,a,n)=>new He(this,o,a,n),UpsampleSigmoid:(o,a)=>new Re(this,o,a),Input:(o,a)=>new rt(this,o,a)},this.presenters={CompositeSolid:(o,a,n)=>new Je(this,o,a,n),CompositeImage:(o,a,n)=>new Ze(this,o,a,n),CompositeImageBilinear:(o,a,n)=>new et(this,o,a,n),CompositePassthrough:o=>new tt(this,o)}}static isAvailable(){let t=null;try{return t=new OffscreenCanvas(1,1).getContext("webgl2"),!(!t||!t.getExtension("EXT_color_buffer_float"))}catch{return!1}finally{t?.getExtension("WEBGL_lose_context")?.loseContext()}}static create(t){let r=t.canvas.getContext("webgl2");if(!r)throw new Error("WebGL2 not available");if(!r.getExtension("EXT_color_buffer_float"))throw new Error("EXT_color_buffer_float not available");return new s(r,t.canvas,t.dtype??"f32")}attachCanvas(t){throw new Error(\`WebGLBackend.attachCanvas('\${t}'): WebGL cannot render to a second canvas; use the renderer's snapshot-and-present path for preview output\`)}bindDisplayFramebuffer(){this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,null),this.gl.viewport(0,0,this.canvas.width,this.canvas.height)}toTextureView(t){if(t===null)return null;let r=this.dtype==="f16",e=t instanceof Uint16Array;return r===e?t:r?re(t):I(t)}tensor(t,r,e,o){let a=r*(e/4),n=t,u=this.gl,p=u.createTexture(),l=this.textureFormat,c=this.toTextureView(o??null);return u.bindTexture(u.TEXTURE_2D,p),u.texImage2D(u.TEXTURE_2D,0,l.internalFormat,a,n,0,l.format,l.type,c),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MIN_FILTER,u.NEAREST),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MAG_FILTER,u.NEAREST),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_S,u.CLAMP_TO_EDGE),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_T,u.CLAMP_TO_EDGE),{h:t,w:r,c:e,texture:p,texW:a,texH:n}}upload(t){return{data:t}}async readback(t){let r=this.gl,e=this.textureFormat;if(r.bindFramebuffer(r.FRAMEBUFFER,this.fbo),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,t.texture,0),this.dtype==="f16"){let a=new Uint16Array(t.texW*t.texH*4);return r.readPixels(0,0,t.texW,t.texH,e.format,r.HALF_FLOAT,a),r.bindFramebuffer(r.FRAMEBUFFER,null),I(a)}let o=new Float32Array(t.texW*t.texH*4);return r.readPixels(0,0,t.texW,t.texH,e.format,r.FLOAT,o),r.bindFramebuffer(r.FRAMEBUFFER,null),o}copyTensor(t,r){if(t.texW!==r.texW||t.texH!==r.texH)throw new Error(\`copyTensor: size mismatch (src \${t.texW}\\xD7\${t.texH} vs dst \${r.texW}\\xD7\${r.texH})\`);let e=this.gl;e.bindFramebuffer(e.FRAMEBUFFER,this.fbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t.texture,0),e.bindTexture(e.TEXTURE_2D,r.texture),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t.texW,t.texH),e.bindFramebuffer(e.FRAMEBUFFER,null)}async sync(){let t=this.gl,r=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);if(!r){t.finish();return}for(t.flush();;){let e=t.clientWaitSync(r,0,0);if(e===t.ALREADY_SIGNALED||e===t.CONDITION_SATISFIED){t.deleteSync(r);return}if(e===t.WAIT_FAILED)throw t.deleteSync(r),new Error("WebGLBackend.sync: clientWaitSync returned WAIT_FAILED");await new Promise(o=>setTimeout(o,1))}}destroy(){this.gl.deleteFramebuffer(this.fbo),this.gl.getExtension("WEBGL_lose_context")?.loseContext()}};var st=U("setup_backend");async function jr(s,t,r={}){let e=s.backend==="webgpu"||s.backend==="auto",o=!!s.outputCanvas,a=()=>s.outputCanvas??new OffscreenCanvas(t.w,t.h),n=null;if(e&&await D.isAvailable()){let p=s.dtype==="f16"&&!await D.hasF16Support()?"f32":s.dtype,l=a();try{let c=await D.create({canvas:l,dtype:p});return c.device.lost.then(m=>{m.reason!=="destroyed"&&r.onContextLost?.({message:\`WebGPU device lost: \${m.reason}\${m.message?" \\u2014 "+m.message:""}\`,source:"backend-lost",recoverable:!1,cause:m})}).catch(()=>{}),{backend:c,resolvedBackend:"webgpu",resolvedDtype:p,canvas:l}}catch(c){st.warn("WebGPU isAvailable but create() threw; trying WebGL fallback:",c),n=c,o&&st.warn("transfer-capture topology: WebGL fallback may also fail on the same canvas")}}if(L.isAvailable()){let p=a();try{let l=L.create({canvas:p,dtype:s.dtype});return p.addEventListener("webglcontextlost",c=>{r.onContextLost?.({message:"WebGL context lost",source:"backend-lost",recoverable:!1,cause:c})}),{backend:l,resolvedBackend:"webgl",resolvedDtype:s.dtype,canvas:p}}catch(l){st.warn("WebGL create() threw:",l),n=l}}let u=n?\` (last error: \${n.message??n})\`:"";throw new Error(\`setup_backend: no usable GPU backend\${u}\`)}var qr=.5,ra=3,Kr=10,oa=30,F=U("autotune");async function Yr(s,t=oa){let r=s instanceof L?qr*.5:qr,e=1e3/t*r;F(\`start; budget per source frame: \${e.toFixed(1)}ms (source \${t}fps \\xD7 \${r} safety)\`),F("backend dtype:",s.dtype);let o=null;for(let a of at){if(!E[a.model]){F("skip",a.model,"(no TIER_CONFIG entry)");continue}try{let n=E[a.model].baseRes;F(\`bench \${a.model} base @ \${n.w}\\xD7\${n.h} skipFrames=\${a.skipFrames} \\u2026\`);let u=await na(s,a),p=u<=e;if(F(\` \${a.model}: \${u.toFixed(1)}ms / source frame \${p?"\\u2713 within budget":"\\u2717 over budget"}\`),(p||o===null)&&(o=a),!p)break}catch(n){F(" bench failed for",a.model,":",n);break}}if(!o)throw new Error("autotune: no implementable preset available");return F("picked",o.model),o}function ia(s){let t=Object.create(s);return t.ops={...s.ops,Conv2d:(r,e,o)=>{let a={weights:new Float32Array(o.kernel*o.kernel*r.c*o.outChannels),bias:new Float32Array(o.outChannels)};return s.ops.Conv2d(r,a,o)},DepthwiseConv2d:(r,e,o)=>{let a={weights:new Float32Array(o.kernel*o.kernel*r.c),bias:new Float32Array(r.c)};return s.ops.DepthwiseConv2d(r,a,o)},Conv2dAdd:(r,e,o,a)=>{let n={weights:new Float32Array(a.kernel*a.kernel*r.c*a.outChannels),bias:new Float32Array(a.outChannels)};return s.ops.Conv2dAdd(r,e,n,a)},UpsampleConv1x1:(r,e,o)=>{let a={weights:new Float32Array(r.c*o.outChannels),bias:new Float32Array(o.outChannels)};return s.ops.UpsampleConv1x1(r,a,o)},ProjResidual:(r,e,o,a)=>{let n={weights:new Float32Array(r.c*a.outChannels),bias:new Float32Array(a.outChannels)};return s.ops.ProjResidual(r,e,n,a)},ConcatConv2d:(r,e,o,a)=>{let n={weights:new Float32Array(9*(r.c+e.c)*a.outChannels),bias:new Float32Array(a.outChannels)};return s.ops.ConcatConv2d(r,e,n,a)}},t}function aa(){let s=new Proxy({},{get:()=>s});return s}async function na(s,t){let r=E[t.model];if(!r)throw new Error(\`microbench: no TIER_CONFIG entry for '\${t.model}'\`);let e=r.base,o=ia(s),a=o.tensor(r.baseRes.h,r.baseRes.w,4),n=new e(o,a,aa());for(let c=0;c<ra;c++)n.run(),await s.sync();let u=t.skipFrames+1,p=performance.now();for(let c=0;c<Kr;c++)c%u===0&&n.run();return await s.sync(),(performance.now()-p)/Kr}async function Qr(s,t,r){let e;if(s==="auto")e=await Yr(r);else if(typeof s=="string"){let o=V(s);if(!o)throw new Error(\`resolve_preset: unknown preset name '\${s}'\`);e=o}else e=s;return e.dtype!==t?{...e,dtype:t}:e}function Jr(s){let t=null,r=null;return s.onmessage=e=>{let{frame:o}=e.data;if(r){let a=r;r=null,a(o)}else t&&t.close(),t=o},s.start?.(),new ReadableStream({pull(e){if(t){e.enqueue(t),t=null;return}return new Promise(o=>{r=a=>{e.enqueue(a),o()}})},cancel(){t&&(t.close(),t=null),s.close()}},{highWaterMark:0})}function Zr(s){switch(s.topology.input){case"mstp":if(!s.inputReadable)throw new Error("create_input: topology.input='mstp' but InitData.inputReadable missing");return s.inputReadable;case"rvfc-postmessage":if(!s.inputPort)throw new Error("create_input: topology.input='rvfc-postmessage' but InitData.inputPort missing");return Jr(s.inputPort)}}function eo(s){return new TransformStream({transform(t,r){s.process(t);let e=new VideoFrame(s.canvas,{timestamp:t.timestamp});t.close(),r.enqueue(e)}})}function to(s){return new WritableStream({write(t){s.process(t),t.close()}})}function ro(s,t){return new WritableStream({write(r){s.process(r),r.close();let e=s.canvas.transferToImageBitmap();t.postMessage({bmp:e},[e])},close(){t.close()}})}var sa=U("create_output");function oo(s,t,r){switch(s.topology.output){case"mstg":{if(!s.outputWritable)throw new Error("create_output: topology.output='mstg' but InitData.outputWritable missing");let e=eo(t);return e.readable.pipeTo(s.outputWritable,{signal:r}).catch(o=>{r.aborted||sa.warn("mstg downstream pipe failed:",o)}),e.writable}case"transfer-capture":return to(t);case"bitmap-shuttle":{if(!s.outputPort)throw new Error("create_output: topology.output='bitmap-shuttle' but InitData.outputPort missing");return ro(t,s.outputPort)}}}function io(s){if(!s.onFirstFrame)return s.input.pipeTo(s.output,{signal:s.signal});let t=!1,r=s.onFirstFrame,e=new TransformStream({transform(o,a){a.enqueue(o),t||(t=!0,queueMicrotask(r))}});return s.input.pipeThrough(e,{signal:s.signal}).pipeTo(s.output,{signal:s.signal})}var C=U("worker");C("script loaded");var W=null,A=null,ot=null;self.onmessage=async function(s){let{cmd:t,data:r,request_id:e}=s.data;C("cmd received:",t,"request_id:",e);try{let o=await ua(t,r);C("cmd ok:",t),va(e,o)}catch(o){C("cmd FAILED:",t,o),H("error",{message:\`\${t} failed: \${o.message??String(o)}\`,source:"worker",recoverable:!1,cause:o})}};async function ua(s,t){switch(s){case"init":return pa(t);case"startRender":return la(t.weights);case"setBackground":return ca(t);case"setEnabled":return da(t.enabled);case"setPreset":return ga(t);case"getStats":return W?.getStats()??null;case"destroy":return _a();case"attachPreview":return ma(t);case"setPreview":return fa(t);case"clearPreview":return ha();default:throw new Error(\`unknown cmd: \${s}\`)}}async function pa(s){if(lt(!!s.debug),C("handleInit: start; topology=",s.topology,"preset=",s.preset,"backend=",s.backend,"dtype=",s.dtype),W)throw new Error("handleInit: already initialized");C("handleInit: setupBackend\\u2026");let t=await jr(s,s.canvasSize,{onContextLost:a=>{C("GPU context lost:",a.message),H("error",a)}});C("handleInit: backend ready:",t.resolvedBackend,t.resolvedDtype,"canvas:",t.canvas.width,"x",t.canvas.height),C("handleInit: constructing Renderer (boot mode)\\u2026"),W=new te({backend:t.backend,backendKind:t.resolvedBackend,canvas:t.canvas,background:s.background,enabled:s.enabled,topology:s.topology}),A=new AbortController,C("handleInit: createInputStream\\u2026");let r=Zr(s);C("handleInit: createOutputSink\\u2026");let e=oo(s,W,A.signal);C("handleInit: starting pipe (passthrough)\\u2026"),io({input:r,output:e,signal:A.signal}).then(()=>{C("pipe completed (input ended)")}).catch(a=>{if(A?.signal.aborted){C("pipe aborted (expected on destroy)");return}C("pipe FAILED:",a),H("error",{message:\`pipe failed: \${a.message}\`,source:"worker",recoverable:!1,cause:a})}),C("handleInit: resolvePreset\\u2026");let o=await Qr(s.preset,t.resolvedDtype,t.backend);return C("handleInit: preset resolved:",o),ot=o,C("handleInit: done; returning InitResponse, awaiting startRender"),{resolvedPreset:o,resolvedBackend:t.resolvedBackend,resolvedDtype:t.resolvedDtype}}async function la(s){if(C("handleStartRender: start; weights bytes:",s.byteLength),!W||!ot)throw new Error("handleStartRender: handleInit not completed");C("handleStartRender: attaching network via setPreset\\u2026"),W.setPreset(ot,s),C("handleStartRender: ready (effect mode active)"),H("ready",void 0)}async function ca(s){W?.setBackground(s)}async function da(s){W?.setEnabled(s)}async function ma(s){if(!W)throw new Error("handleAttachPreview: not initialized");W.attachPreview(s.canvas)}async function fa(s){if(!W)throw new Error("handleSetPreview: not initialized");W.setPreview(s.background,s.fps!==void 0?{fps:s.fps}:void 0)}async function ha(){W?.clearPreview()}async function ga(s){if(!W)throw new Error("handleSetPreset: not initialized");if(!s.weights)throw new Error("handleSetPreset: weights required for runtime preset swap");if(s.preset==="auto")throw new Error("handleSetPreset: 'auto' not supported on runtime swap (use at init for autotune)");let t=typeof s.preset=="string"?V(s.preset)??ba(s.preset):s.preset;return W.setPreset(t,s.weights),{resolvedPreset:t}}async function _a(){A?.abort(),A=null,W?.destroy(),W=null,ot=null}function ba(s){throw new Error(\`handleSetPreset: unknown preset '\${s}'\`)}function va(s,t){let r={request_id:s,res:t};self.postMessage(r)}function H(s,t){let r={request_id:s,res:t};self.postMessage(r)}function Mh(s){H("stats",s)}export{Mh as emitStats};
3805
- `;var y=x("pipeline");function Qt(){{let a=new Blob([he],{type:"application/javascript"}),t=URL.createObjectURL(a),e=new Worker(t,{type:"module"});return URL.revokeObjectURL(t),e}}var Jt="https://cdn.longpipe.dev/models/v/0.0.2/",Zt={background:"blur",preset:"auto",weightsBaseUrl:Jt,audio:"passthrough",enabled:true,adaptive:true,debug:false},Ge={w:1280,h:720};function er(a,t){if(t)return t;let r=a.getVideoTracks()[0]?.getSettings()??{};return {w:r.width||Ge.w,h:r.height||Ge.h}}function Ee(a,t){return `${a.replace(/\/$/,"")}/model_${t}.bin`}var fe=class{stream;ready;controller;worker;inputCleanup;outputCleanup;adaptive=null;bgCleanup=null;previewBgCleanup=null;constructor(t,e){let r={...Zt,...e};me(r.debug);let n=ye(),i=Ue(n.input,t),o=er(t,r.outputResolution),u=Se(n.output,o);this.inputCleanup=i.cleanup,this.outputCleanup=u.cleanup,this.stream=ke(u.videoTrack,t,r.audio),u.startPassthrough?.(t),this.worker=Qt(),this.controller=new O(this.worker),this.ready=new Promise((c,h)=>{this.controller.addPersistentListener("ready",()=>{y("ready handler invoked; resolving .ready"),r.onReady?.(),c();}),this.controller.addPersistentListener("error",f=>{console.error(`[longpipe/pipeline] error (${f.source}):`,f.message),f.recoverable||h(new Error(f.message)),r.onError?.(f);});});let s={topology:n,preset:r.preset,enabled:r.enabled,backend:"auto",dtype:"f16",canvasSize:o,debug:r.debug,...i.initFields,...u.initFields},l=[...i.transferList,...u.transferList];this.bootstrap(s,r.background,l,r.weightsBaseUrl,r.adaptive,r.onError);}async bootstrap(t,e,r,n,i,o){try{y("normalizing background\u2026");let u=await E(e);this.bgCleanup=u.cleanup??null;let s={...t,background:u.background},l=[...r,...u.transferList??[]];y("sending init\u2026");let c=await this.controller.sendMessage("init",s,l);y("init resolved:",c);let h=Ee(n,c.resolvedPreset.model);y("fetching weights:",h);let f=await fetch(h);if(!f.ok)throw new Error(`weights fetch failed: ${f.status} ${h}`);let v=await f.arrayBuffer();y("weights bytes:",v.byteLength),y("sending startRender\u2026"),await this.controller.sendMessage("startRender",{weights:v},[v]),y("startRender resolved; awaiting first frame"),s.preset==="auto"&&i&&(this.adaptive=new G({backendKind:c.resolvedBackend,initialModel:c.resolvedPreset.model,weightsBaseUrl:n,buildWeightsUrl:Ee,getStats:()=>this.getStats(),swapPreset:async(I,le)=>{await this.controller.sendMessage("setPreset",{preset:I,weights:le},[le]);},onError:o}),this.adaptive.start());}catch(u){console.error("[longpipe/pipeline] bootstrap failed:",u),this.controller.handleMessage.call(this.controller,{data:{request_id:"error",res:{message:u.message??String(u),source:"worker",recoverable:false,cause:u}}});}}then(t,e){return this.ready.then(()=>t?t(this):this,e)}async setBackground(t){let e=await E(t),r=this.bgCleanup;this.bgCleanup=e.cleanup??null,await this.controller.sendMessage("setBackground",e.background,e.transferList),r?.();}setPreset(t,e){this.controller.sendMessage("setPreset",{preset:t,weights:e});}attachPreview(t){let e=t.transferControlToOffscreen();this.controller.sendMessage("attachPreview",{canvas:e},[e]);}async setPreview(t){let e=await E(t.background),r=this.previewBgCleanup;this.previewBgCleanup=e.cleanup??null,await this.controller.sendMessage("setPreview",{background:e.background,fps:t.fps},e.transferList),r?.();}clearPreview(){this.controller.sendMessage("clearPreview",{}),this.previewBgCleanup?.(),this.previewBgCleanup=null;}setEnabled(t){this.controller.sendMessage("setEnabled",{enabled:t});}async getStats(){return this.controller.sendMessage("getStats",{})}destroy(){this.adaptive?.stop(),this.adaptive=null,this.bgCleanup?.(),this.bgCleanup=null,this.previewBgCleanup?.(),this.previewBgCleanup=null,this.controller.sendMessage("destroy",{}),this.controller.terminate(),this.inputCleanup(),this.outputCleanup();}};var T=new Float32Array(1),U=new Uint32Array(T.buffer);function tr(a){T[0]=a;let t=U[0],e=t>>>16&32768,r=t&2147483647,n=(r>>>23)-127+15;if((t&2139095040)===2139095040)return (t&8388607)!==0?e|32256:e|31744;if(n>=31)return e|31744;if(n<=0){if(n<-10)return e;let l=r&8388607|8388608,c=14-n,h=l>>>c,f=l>>>c-1&1,v=(l&(1<<c-1)-1)!==0?1:0;return f&&(v||h&1)&&(h+=1),e|h}let i=r>>>13&1023,o=r>>>12&1,u=(r&4095)!==0?1:0,s=n<<10|i;return o&&(u||i&1)&&(s+=1,(s>>>10&31)===31)?e|31744:e|s}function rr(a){let t=(a&32768)<<16,e=(a&31744)>>>10,r=a&1023;if(e===0){if(r===0)return U[0]=t,T[0];let n=r,i=1;for(;(n&1024)===0;)n<<=1,i-=1;return n&=1023,U[0]=t|i+127-15<<23|n<<13,T[0]}return e===31?(U[0]=t|2139095040|r<<13,T[0]):(U[0]=t|e+127-15<<23|r<<13,T[0])}function Fe(a){let t=new Uint16Array(a.length);for(let e=0;e<a.length;e++)t[e]=tr(a[e]);return t}function ge(a){let t=new Float32Array(a.length);for(let e=0;e<a.length;e++)t[e]=rr(a[e]);return t}var p=class{constructor(t){this.backend=t;}backend;shader="";pipeline;bindGroup;uniformDefs=[];uniformBuffers={};createUniform(t,e){this.uniformDefs.push({name:t,type:e});}setUniform(t,e){let r=this.backend.device.createBuffer({size:e.byteLength,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,mappedAtCreation:true});e instanceof Uint32Array?new Uint32Array(r.getMappedRange()).set(e):new Float32Array(r.getMappedRange()).set(e),r.unmap(),this.uniformBuffers[t]=r;}defaultBindGroup(){let t=[],e=0;for(let r of this.inputs)t.push({binding:e++,resource:{buffer:r.buffer}});for(let r of this.weights)t.push({binding:e++,resource:{buffer:r.buffer}});for(let r of this.uniformDefs)t.push({binding:e++,resource:{buffer:this.uniformBuffers[r.name]}});return t.push({binding:e,resource:{buffer:this.output.buffer}}),this.backend.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:t})}defaultSetup(){let t=this.backend.device.createShaderModule({code:this.shader});this.pipeline=this.backend.device.createComputePipeline({layout:"auto",compute:{module:t,entryPoint:"main"}}),this.bindGroup=this.defaultBindGroup();}run(){let t=this.backend.device.createCommandEncoder(),e=t.beginComputePass();e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.dispatchWorkgroups(...this.dispatch),e.end(),this.backend.device.queue.submit([t.finish()]);}};var Ae=`// Conv2d, output-channel-blocked (K=4) \u2014 drop-in replacement for conv2d.wgsl.
4383
+ void main() { gl_Position = vec4(VERTS[gl_VertexID], 0.0, 1.0); }\`,gt=class{constructor(t,r,e){a(this,"backend",t);a(this,"output");a(this,"gl");a(this,"program");a(this,"srcTex");a(this,"uOutW");a(this,"uOutH");a(this,"uSrc");a(this,"source",null);let i=t.gl;this.gl=i,this.output=t.tensor(r,e,4),this.srcTex=i.createTexture(),i.bindTexture(i.TEXTURE_2D,this.srcTex),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE);let o=i.createShader(i.VERTEX_SHADER);i.shaderSource(o,Va),i.compileShader(o);let n=i.createShader(i.FRAGMENT_SHADER);if(i.shaderSource(n,xo),i.compileShader(n),!i.getShaderParameter(n,i.COMPILE_STATUS))throw new Error(\`Input GLSL compile error: \${i.getShaderInfoLog(n)}\`);if(this.program=i.createProgram(),i.attachShader(this.program,o),i.attachShader(this.program,n),i.linkProgram(this.program),!i.getProgramParameter(this.program,i.LINK_STATUS))throw new Error(\`Input GLSL link error: \${i.getProgramInfoLog(this.program)}\`);this.uSrc=i.getUniformLocation(this.program,"u_src"),this.uOutW=i.getUniformLocation(this.program,"u_out_w"),this.uOutH=i.getUniformLocation(this.program,"u_out_h")}setSource(t){this.source=t}run(){if(!this.source)throw new Error("InputWebGL.run() called before setSource()");let t=this.gl;t.bindTexture(t.TEXTURE_2D,this.srcTex),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.source),t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.srcTex),t.uniform1i(this.uSrc,0),t.uniform1i(this.uOutW,this.output.w),t.uniform1i(this.uOutH,this.output.h),t.bindFramebuffer(t.FRAMEBUFFER,this.backend.fbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.output.texture,0),t.viewport(0,0,this.output.texW,this.output.texH),t.bindVertexArray(null),t.drawArrays(t.TRIANGLES,0,6)}};var F=class u{constructor(t,r,e){a(this,"gl",t);a(this,"canvas",r);a(this,"dtype",e);a(this,"ops");a(this,"presenters");a(this,"fbo");a(this,"textureFormat");this.fbo=t.createFramebuffer(),this.textureFormat=e==="f16"?{internalFormat:t.RGBA16F,format:t.RGBA,type:t.HALF_FLOAT,bytesPerElement:2}:{internalFormat:t.RGBA32F,format:t.RGBA,type:t.FLOAT,bytesPerElement:4},this.ops={Conv2d:(i,o,n)=>new He(this,i,o,n),ConvTranspose2d:(i,o,n)=>new ze(this,i,o,n),DepthwiseConv2d:(i,o,n)=>new Ve(this,i,o,n),Add:(i,o)=>new Ne(this,i,o),Sigmoid:i=>new $e(this,i),Tanh:i=>new Xe(this,i),ElementwiseMul:(i,o)=>new je(this,i,o),Warp:(i,o,n)=>new qe(this,i,o,n),Stabilize:(i,o,n,s,p)=>new Ke(this,i,o,n,s,p),BilinearUpsample:(i,o)=>new Ye(this,i,o),Crop:(i,o)=>new Qe(this,i,o),BicubicUpsample:(i,o)=>new Je(this,i,o),ChannelConcat:(i,o)=>new Ze(this,i,o),Conv2dAdd:(i,o,n,s)=>new ot(this,i,o,n,s),ProjResidual:(i,o,n,s)=>new it(this,i,o,n,s),ConcatConv2d:(i,o,n,s)=>new at(this,i,o,n,s),GatesFused:(i,o,n)=>new nt(this,i,o,n),CandUpdateFused:(i,o,n,s,p)=>new st(this,i,o,n,s,p),ConvExpand:(i,o)=>new ut(this,i,o),CatConv6to2:(i,o,n)=>new pt(this,i,o,n),DownAdapter:(i,o,n,s)=>new lt(this,i,o,n,s),UpFinal:(i,o,n)=>new ct(this,i,o,n),UpFinalSkip:(i,o,n,s)=>new dt(this,i,o,n,s),UpsampleConcat:(i,o,n)=>new tt(this,i,o,n),UpsampleConv1x1:(i,o,n)=>new rt(this,i,o,n),UpsampleSigmoid:(i,o)=>new et(this,i,o),Input:(i,o)=>new gt(this,i,o)},this.presenters={CompositeSolid:(i,o,n)=>new mt(this,i,o,n),CompositeImage:(i,o,n)=>new ft(this,i,o,n),CompositeImageBilinear:(i,o,n)=>new ht(this,i,o,n),CompositePassthrough:i=>new _t(this,i)}}static isAvailable(){let t=null;try{return t=new OffscreenCanvas(1,1).getContext("webgl2"),!(!t||!t.getExtension("EXT_color_buffer_float"))}catch{return!1}finally{t?.getExtension("WEBGL_lose_context")?.loseContext()}}static create(t){let r=t.canvas.getContext("webgl2");if(!r)throw new Error("WebGL2 not available");if(!r.getExtension("EXT_color_buffer_float"))throw new Error("EXT_color_buffer_float not available");return new u(r,t.canvas,t.dtype??"f32")}attachCanvas(t){throw new Error(\`WebGLBackend.attachCanvas('\${t}'): WebGL cannot render to a second canvas; use the renderer's snapshot-and-present path for preview output\`)}bindDisplayFramebuffer(){this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,null),this.gl.viewport(0,0,this.canvas.width,this.canvas.height)}toTextureView(t){if(t===null)return null;let r=this.dtype==="f16",e=t instanceof Uint16Array;return r===e?t:r?pe(t):A(t)}tensor(t,r,e,i){let o=r*(e/4),n=t,s=this.gl,p=s.createTexture(),l=this.textureFormat,c=this.toTextureView(i??null);return s.bindTexture(s.TEXTURE_2D,p),s.texImage2D(s.TEXTURE_2D,0,l.internalFormat,o,n,0,l.format,l.type,c),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,s.NEAREST),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,s.NEAREST),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_S,s.CLAMP_TO_EDGE),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_T,s.CLAMP_TO_EDGE),{h:t,w:r,c:e,texture:p,texW:o,texH:n}}upload(t){return{data:t}}async readback(t){let r=this.gl,e=this.textureFormat;if(r.bindFramebuffer(r.FRAMEBUFFER,this.fbo),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,t.texture,0),this.dtype==="f16"){let o=new Uint16Array(t.texW*t.texH*4);return r.readPixels(0,0,t.texW,t.texH,e.format,r.HALF_FLOAT,o),r.bindFramebuffer(r.FRAMEBUFFER,null),A(o)}let i=new Float32Array(t.texW*t.texH*4);return r.readPixels(0,0,t.texW,t.texH,e.format,r.FLOAT,i),r.bindFramebuffer(r.FRAMEBUFFER,null),i}copyTensor(t,r){if(t.texW!==r.texW||t.texH!==r.texH)throw new Error(\`copyTensor: size mismatch (src \${t.texW}\\xD7\${t.texH} vs dst \${r.texW}\\xD7\${r.texH})\`);let e=this.gl;e.bindFramebuffer(e.FRAMEBUFFER,this.fbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t.texture,0),e.bindTexture(e.TEXTURE_2D,r.texture),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t.texW,t.texH),e.bindFramebuffer(e.FRAMEBUFFER,null)}async sync(){let t=this.gl,r=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);if(!r){t.finish();return}for(t.flush();;){let e=t.clientWaitSync(r,0,0);if(e===t.ALREADY_SIGNALED||e===t.CONDITION_SATISFIED){t.deleteSync(r);return}if(e===t.WAIT_FAILED)throw t.deleteSync(r),new Error("WebGLBackend.sync: clientWaitSync returned WAIT_FAILED");await new Promise(i=>setTimeout(i,1))}}destroy(){this.gl.deleteFramebuffer(this.fbo),this.gl.getExtension("WEBGL_lose_context")?.loseContext()}};var Tt=S("setup_backend");async function yo(u,t,r={}){let e=u.backend==="webgpu"||u.backend==="auto",i=!!u.outputCanvas,o=()=>u.outputCanvas??new OffscreenCanvas(t.w,t.h),n=null;if(e&&await R.isAvailable()){let p=u.dtype==="f16"&&!await R.hasF16Support()?"f32":u.dtype,l=o();try{let c=await R.create({canvas:l,dtype:p});return c.device.lost.then(d=>{d.reason!=="destroyed"&&r.onContextLost?.({message:\`WebGPU device lost: \${d.reason}\${d.message?" \\u2014 "+d.message:""}\`,source:"backend-lost",recoverable:!1,cause:d})}).catch(()=>{}),{backend:c,resolvedBackend:"webgpu",resolvedDtype:p,canvas:l}}catch(c){Tt.warn("WebGPU isAvailable but create() threw; trying WebGL fallback:",c),n=c,i&&Tt.warn("transfer-capture topology: WebGL fallback may also fail on the same canvas")}}if(F.isAvailable()){let p=o();try{let l=F.create({canvas:p,dtype:u.dtype});return p.addEventListener("webglcontextlost",c=>{r.onContextLost?.({message:"WebGL context lost",source:"backend-lost",recoverable:!1,cause:c})}),{backend:l,resolvedBackend:"webgl",resolvedDtype:u.dtype,canvas:p}}catch(l){Tt.warn("WebGL create() threw:",l),n=l}}let s=n?\` (last error: \${n.message??n})\`:"";throw new Error(\`setup_backend: no usable GPU backend\${s}\`)}var wo=.5,Na=3,ko=10,$a=30,E=S("autotune");async function To(u,t=$a){let r=u instanceof F?wo*.5:wo,e=1e3/t*r;E(\`start; budget per source frame: \${e.toFixed(1)}ms (source \${t}fps \\xD7 \${r} safety)\`),E("backend dtype:",u.dtype);let i=null;for(let o of yt){if(!O[o.model]){E("skip",o.model,"(no TIER_CONFIG entry)");continue}try{let n=O[o.model].baseRes;E(\`bench \${o.model} base @ \${n.w}\\xD7\${n.h} skipFrames=\${o.skipFrames} \\u2026\`);let s=await qa(u,o),p=s<=e;if(E(\` \${o.model}: \${s.toFixed(1)}ms / source frame \${p?"\\u2713 within budget":"\\u2717 over budget"}\`),(p||i===null)&&(i=o),!p)break}catch(n){E(" bench failed for",o.model,":",n);break}}if(!i)throw new Error("autotune: no implementable preset available");return E("picked",i.model),i}function Xa(u){let t=Object.create(u);return t.ops={...u.ops,Conv2d:(r,e,i)=>{let o={weights:new Float32Array(i.kernel*i.kernel*r.c*i.outChannels),bias:new Float32Array(i.outChannels)};return u.ops.Conv2d(r,o,i)},DepthwiseConv2d:(r,e,i)=>{let o={weights:new Float32Array(i.kernel*i.kernel*r.c),bias:new Float32Array(r.c)};return u.ops.DepthwiseConv2d(r,o,i)},Conv2dAdd:(r,e,i,o)=>{let n={weights:new Float32Array(o.kernel*o.kernel*r.c*o.outChannels),bias:new Float32Array(o.outChannels)};return u.ops.Conv2dAdd(r,e,n,o)},UpsampleConv1x1:(r,e,i)=>{let o={weights:new Float32Array(r.c*i.outChannels),bias:new Float32Array(i.outChannels)};return u.ops.UpsampleConv1x1(r,o,i)},ProjResidual:(r,e,i,o)=>{let n={weights:new Float32Array(r.c*o.outChannels),bias:new Float32Array(o.outChannels)};return u.ops.ProjResidual(r,e,n,o)},ConcatConv2d:(r,e,i,o)=>{let n={weights:new Float32Array(9*(r.c+e.c)*o.outChannels),bias:new Float32Array(o.outChannels)};return u.ops.ConcatConv2d(r,e,n,o)}},t}function ja(){let u=new Proxy({},{get:()=>u});return u}async function qa(u,t){let r=O[t.model];if(!r)throw new Error(\`microbench: no TIER_CONFIG entry for '\${t.model}'\`);let e=r.base,i=Xa(u),o=i.tensor(r.baseRes.h,r.baseRes.w,4),n=new e(i,o,ja());for(let c=0;c<Na;c++)n.run(),await u.sync();let s=t.skipFrames+1,p=performance.now();for(let c=0;c<ko;c++)c%s===0&&n.run();return await u.sync(),(performance.now()-p)/ko}async function Co(u,t,r){let e;if(u==="auto")e=await To(r);else if(typeof u=="string"){let i=q(u);if(!i)throw new Error(\`resolve_preset: unknown preset name '\${u}'\`);e=i}else e=u;return e.dtype!==t?{...e,dtype:t}:e}function Wo(u){let t=null,r=null;return u.onmessage=e=>{let{frame:i}=e.data;if(r){let o=r;r=null,o(i)}else t&&t.close(),t=i},u.start?.(),new ReadableStream({pull(e){if(t){e.enqueue(t),t=null;return}return new Promise(i=>{r=o=>{e.enqueue(o),i()}})},cancel(){t&&(t.close(),t=null),u.close()}},{highWaterMark:0})}function Po(u){switch(u.topology.input){case"mstp":if(!u.inputReadable)throw new Error("create_input: topology.input='mstp' but InitData.inputReadable missing");return u.inputReadable;case"rvfc-postmessage":if(!u.inputPort)throw new Error("create_input: topology.input='rvfc-postmessage' but InitData.inputPort missing");return Wo(u.inputPort)}}function Go(u){return new TransformStream({transform(t,r){u.process(t);let e=new VideoFrame(u.canvas,{timestamp:t.timestamp});t.close(),r.enqueue(e)}})}function Bo(u){return new WritableStream({write(t){u.process(t),t.close()}})}function Uo(u,t){return new WritableStream({write(r){u.process(r),r.close();let e=u.canvas.transferToImageBitmap();t.postMessage({bmp:e},[e])},close(){t.close()}})}var Ka=S("create_output");function So(u,t,r){switch(u.topology.output){case"mstg":{if(!u.outputWritable)throw new Error("create_output: topology.output='mstg' but InitData.outputWritable missing");let e=Go(t);return e.readable.pipeTo(u.outputWritable,{signal:r}).catch(i=>{r.aborted||Ka.warn("mstg downstream pipe failed:",i)}),e.writable}case"transfer-capture":return Bo(t);case"bitmap-shuttle":{if(!u.outputPort)throw new Error("create_output: topology.output='bitmap-shuttle' but InitData.outputPort missing");return Uo(t,u.outputPort)}}}function Lo(u){if(!u.onFirstFrame)return u.input.pipeTo(u.output,{signal:u.signal});let t=!1,r=u.onFirstFrame,e=new TransformStream({transform(i,o){o.enqueue(i),t||(t=!0,queueMicrotask(r))}});return u.input.pipeThrough(e,{signal:u.signal}).pipeTo(u.output,{signal:u.signal})}var W=S("worker");W("script loaded");var P=null,H=null,bt=null;self.onmessage=async function(u){let{cmd:t,data:r,request_id:e}=u.data;W("cmd received:",t,"request_id:",e);try{let i=await Ya(t,r);W("cmd ok:",t),un(e,i)}catch(i){W("cmd FAILED:",t,i),$("error",{message:\`\${t} failed: \${i.message??String(i)}\`,source:"worker",recoverable:!1,cause:i})}};async function Ya(u,t){switch(u){case"init":return Qa(t);case"startRender":return Ja(t.weights);case"setBackground":return Za(t);case"setEnabled":return en(t.enabled);case"setPreset":return an(t);case"getStats":return P?.getStats()??null;case"destroy":return nn();case"attachPreview":return tn(t);case"setPreview":return rn(t);case"clearPreview":return on();default:throw new Error(\`unknown cmd: \${u}\`)}}async function Qa(u){if(Ct(!!u.debug),W("handleInit: start; topology=",u.topology,"preset=",u.preset,"backend=",u.backend,"dtype=",u.dtype),P)throw new Error("handleInit: already initialized");W("handleInit: setupBackend\\u2026");let t=await yo(u,u.canvasSize,{onContextLost:o=>{W("GPU context lost:",o.message),$("error",o)}});W("handleInit: backend ready:",t.resolvedBackend,t.resolvedDtype,"canvas:",t.canvas.width,"x",t.canvas.height),W("handleInit: constructing Renderer (boot mode)\\u2026"),P=new ue({backend:t.backend,backendKind:t.resolvedBackend,canvas:t.canvas,background:u.background,enabled:u.enabled,topology:u.topology}),H=new AbortController,W("handleInit: createInputStream\\u2026");let r=Po(u);W("handleInit: createOutputSink\\u2026");let e=So(u,P,H.signal);W("handleInit: starting pipe (passthrough)\\u2026"),Lo({input:r,output:e,signal:H.signal}).then(()=>{W("pipe completed (input ended)")}).catch(o=>{if(H?.signal.aborted){W("pipe aborted (expected on destroy)");return}W("pipe FAILED:",o),$("error",{message:\`pipe failed: \${o.message}\`,source:"worker",recoverable:!1,cause:o})}),W("handleInit: resolvePreset\\u2026");let i=await Co(u.preset,t.resolvedDtype,t.backend);return W("handleInit: preset resolved:",i),bt=i,W("handleInit: done; returning InitResponse, awaiting startRender"),{resolvedPreset:i,resolvedBackend:t.resolvedBackend,resolvedDtype:t.resolvedDtype}}async function Ja(u){if(W("handleStartRender: start; weights bytes:",u.byteLength),!P||!bt)throw new Error("handleStartRender: handleInit not completed");W("handleStartRender: attaching network via setPreset\\u2026"),P.setPreset(bt,u),W("handleStartRender: ready (effect mode active)"),$("ready",void 0)}async function Za(u){P?.setBackground(u)}async function en(u){P?.setEnabled(u)}async function tn(u){if(!P)throw new Error("handleAttachPreview: not initialized");P.attachPreview(u.canvas)}async function rn(u){if(!P)throw new Error("handleSetPreview: not initialized");P.setPreview(u.background,u.fps!==void 0?{fps:u.fps}:void 0)}async function on(){P?.clearPreview()}async function an(u){if(!P)throw new Error("handleSetPreset: not initialized");if(!u.weights)throw new Error("handleSetPreset: weights required for runtime preset swap");if(u.preset==="auto")throw new Error("handleSetPreset: 'auto' not supported on runtime swap (use at init for autotune)");let t=typeof u.preset=="string"?q(u.preset)??sn(u.preset):u.preset;return P.setPreset(t,u.weights),{resolvedPreset:t}}async function nn(){H?.abort(),H=null,P?.destroy(),P=null,bt=null}function sn(u){throw new Error(\`handleSetPreset: unknown preset '\${u}'\`)}function un(u,t){let r={request_id:u,res:t};self.postMessage(r)}function $(u,t){let r={request_id:u,res:t};self.postMessage(r)}function Vg(u){$("stats",u)}export{Vg as emitStats};
4384
+ `;var k=x("pipeline");function Er(){{let a=new Blob([xe],{type:"application/javascript"}),t=URL.createObjectURL(a),e=new Worker(t,{type:"module"});return URL.revokeObjectURL(t),e}}var Gr="https://cdn.longpipe.dev/models/v/0.0.4/",Fr={background:"blur",preset:"auto",weightsBaseUrl:Gr,audio:"passthrough",enabled:true,adaptive:true,debug:false},qe={w:1280,h:720};function Ar(a,t){if(t)return t;let r=a.getVideoTracks()[0]?.getSettings()??{};return {w:r.width||qe.w,h:r.height||qe.h}}function Xe(a,t,e){let r=e==="f16"?".f16.bin":".bin";return `${a.replace(/\/$/,"")}/model_${t}${r}`}async function Ke(a,t,e){if(e==="f16"){let i=await fetch(Xe(a,t,"f16"));if(i.ok)return i.arrayBuffer()}let r=Xe(a,t,"f32"),n=await fetch(r);if(!n.ok)throw new Error(`weights fetch failed: ${n.status} ${r}`);return n.arrayBuffer()}var we=class{stream;ready;controller;worker;inputCleanup;outputCleanup;adaptive=null;denoiser=null;bgCleanup=null;previewBgCleanup=null;constructor(t,e){let r={...Fr,...e};Te(r.debug);let n=Se(),i=Le(n.input,t),o=Ar(t,r.outputResolution),s=je(n.output,o);this.inputCleanup=i.cleanup,this.outputCleanup=s.cleanup;let u=Ee(r.audio),l;if(u.mode==="denoise"){let h=t.getAudioTracks()[0];h?(this.denoiser=new O(h,{model:u.denoise?.model??"auto",weightsBaseUrl:r.weightsBaseUrl,postFilterBeta:u.denoise?.postFilterBeta,gruLeak:u.denoise?.gruLeak,enabled:u.denoise?.enabled,onError:m=>r.onError?.({message:m,source:"audio",recoverable:true})}),l=this.denoiser.outputTrack):r.onError?.({message:'audio: "denoise" requested but the input stream has no audio track',source:"audio",recoverable:true});}this.stream=Ge(s.videoTrack,t,u,l),s.startPassthrough?.(t),this.worker=Er(),this.controller=new z(this.worker),this.ready=new Promise((h,m)=>{this.controller.addPersistentListener("ready",()=>{k("ready handler invoked; resolving .ready"),r.onReady?.(),h();}),this.controller.addPersistentListener("error",w=>{console.error(`[longpipe/pipeline] error (${w.source}):`,w.message),w.recoverable||m(new Error(w.message)),r.onError?.(w);});});let c={topology:n,preset:r.preset,enabled:r.enabled,backend:"auto",dtype:"f16",canvasSize:o,debug:r.debug,...i.initFields,...s.initFields},f=[...i.transferList,...s.transferList];this.bootstrap(c,r.background,f,r.weightsBaseUrl,r.adaptive,r.onError);}async bootstrap(t,e,r,n,i,o){try{k("normalizing background\u2026");let s=await F(e);this.bgCleanup=s.cleanup??null;let u={...t,background:s.background},l=[...r,...s.transferList??[]];k("sending init\u2026");let c=await this.controller.sendMessage("init",u,l);k("init resolved:",c),k("fetching weights:",c.resolvedPreset.model,c.resolvedDtype);let f=await Ke(n,c.resolvedPreset.model,c.resolvedDtype);k("weights bytes:",f.byteLength),k("sending startRender\u2026"),await this.controller.sendMessage("startRender",{weights:f},[f]),k("startRender resolved; awaiting first frame"),u.preset==="auto"&&i&&(this.adaptive=new G({backendKind:c.resolvedBackend,initialModel:c.resolvedPreset.model,fetchWeights:h=>Ke(n,h,c.resolvedDtype),getStats:()=>this.getStats(),swapPreset:async(h,m)=>{await this.controller.sendMessage("setPreset",{preset:h,weights:m},[m]);},onError:o}),this.adaptive.start());}catch(s){console.error("[longpipe/pipeline] bootstrap failed:",s),this.controller.handleMessage.call(this.controller,{data:{request_id:"error",res:{message:s.message??String(s),source:"worker",recoverable:false,cause:s}}});}}then(t,e){return this.ready.then(()=>t?t(this):this,e)}async setBackground(t){let e=await F(t),r=this.bgCleanup;this.bgCleanup=e.cleanup??null,await this.controller.sendMessage("setBackground",e.background,e.transferList),r?.();}setPreset(t,e){this.controller.sendMessage("setPreset",{preset:t,weights:e});}attachPreview(t){let e=t.transferControlToOffscreen();this.controller.sendMessage("attachPreview",{canvas:e},[e]);}async setPreview(t){let e=await F(t.background),r=this.previewBgCleanup;this.previewBgCleanup=e.cleanup??null,await this.controller.sendMessage("setPreview",{background:e.background,fps:t.fps},e.transferList),r?.();}clearPreview(){this.controller.sendMessage("clearPreview",{}),this.previewBgCleanup?.(),this.previewBgCleanup=null;}setEnabled(t){this.controller.sendMessage("setEnabled",{enabled:t});}async getStats(){return this.controller.sendMessage("getStats",{})}setDenoise(t){if(this.denoiser){if(typeof t=="boolean"){this.denoiser.setEnabled(t);return}(t.postFilterBeta!=null||t.gruLeak!=null)&&this.denoiser.setConfig({postFilterBeta:t.postFilterBeta,gruLeak:t.gruLeak}),t.enabled!=null&&this.denoiser.setEnabled(t.enabled);}}getAudioStats(){return this.denoiser?.getStats()??null}destroy(){this.adaptive?.stop(),this.adaptive=null,this.denoiser?.destroy(),this.denoiser=null,this.bgCleanup?.(),this.bgCleanup=null,this.previewBgCleanup?.(),this.previewBgCleanup=null,this.controller.sendMessage("destroy",{}),this.controller.terminate(),this.inputCleanup(),this.outputCleanup();}};var W=new Float32Array(1),I=new Uint32Array(W.buffer);function Mr(a){W[0]=a;let t=I[0],e=t>>>16&32768,r=t&2147483647,n=(r>>>23)-127+15;if((t&2139095040)===2139095040)return (t&8388607)!==0?e|32256:e|31744;if(n>=31)return e|31744;if(n<=0){if(n<-10)return e;let l=r&8388607|8388608,c=14-n,f=l>>>c,h=l>>>c-1&1,m=(l&(1<<c-1)-1)!==0?1:0;return h&&(m||f&1)&&(f+=1),e|f}let i=r>>>13&1023,o=r>>>12&1,s=(r&4095)!==0?1:0,u=n<<10|i;return o&&(s||i&1)&&(u+=1,(u>>>10&31)===31)?e|31744:e|u}function ye(a){let t=(a&32768)<<16,e=(a&31744)>>>10,r=a&1023;if(e===0){if(r===0)return I[0]=t,W[0];let n=r,i=1;for(;(n&1024)===0;)n<<=1,i-=1;return n&=1023,I[0]=t|i+127-15<<23|n<<13,W[0]}return e===31?(I[0]=t|2139095040|r<<13,W[0]):(I[0]=t|e+127-15<<23|r<<13,W[0])}function Ye(a){let t=new Uint16Array(a.length);for(let e=0;e<a.length;e++)t[e]=Mr(a[e]);return t}function ke(a){let t=new Float32Array(a.length);for(let e=0;e<a.length;e++)t[e]=ye(a[e]);return t}var p=class{constructor(t){this.backend=t;}backend;shader="";pipeline;bindGroup;uniformDefs=[];uniformBuffers={};createUniform(t,e){this.uniformDefs.push({name:t,type:e});}setUniform(t,e){let r=this.backend.device.createBuffer({size:e.byteLength,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,mappedAtCreation:true});e instanceof Uint32Array?new Uint32Array(r.getMappedRange()).set(e):new Float32Array(r.getMappedRange()).set(e),r.unmap(),this.uniformBuffers[t]=r;}defaultBindGroup(){let t=[],e=0;for(let r of this.inputs)t.push({binding:e++,resource:{buffer:r.buffer}});for(let r of this.weights)t.push({binding:e++,resource:{buffer:r.buffer}});for(let r of this.uniformDefs)t.push({binding:e++,resource:{buffer:this.uniformBuffers[r.name]}});return t.push({binding:e,resource:{buffer:this.output.buffer}}),this.backend.device.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:t})}defaultSetup(){let t=this.backend.device.createShaderModule({code:this.shader});this.pipeline=this.backend.device.createComputePipeline({layout:"auto",compute:{module:t,entryPoint:"main"}}),this.bindGroup=this.defaultBindGroup();}run(){let t=this.backend.device.createCommandEncoder(),e=t.beginComputePass();e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.dispatchWorkgroups(...this.dispatch),e.end(),this.backend.device.queue.submit([t.finish()]);}};var Je=`// Conv2d, output-channel-blocked (K=2) \u2014 drop-in replacement for conv2d.wgsl.
3806
4385
  //
3807
- // Identical math, layout, and output to conv2d.wgsl, but each thread computes 4
3808
- // output channel-groups (16 channels) for one pixel, loading each input vec4
3809
- // ONCE and reusing it across all four groups' mat4x4 weight blocks in registers.
3810
- // This reuses the *input* operand (re-read once per output group in the baseline)
3811
- // and is measurably faster end-to-end on WebGPU across devices. Output is
3812
- // bit-identical to conv2d.wgsl (\u22641 ULP from FMA contraction) \u2014 MSE tests pass
3813
- // unchanged. Dispatch ceil(out_groups / 4) in z (see conv2d.ts).
4386
+ // Identical math, layout, and output to conv2d.wgsl, but each thread computes 2
4387
+ // output channel-groups (8 channels) for one pixel, loading each input vec4 ONCE
4388
+ // and reusing it across both groups' mat4x4 weight blocks in registers. Half the
4389
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
4390
+ // identical to conv2d.wgsl (\u22641 ULP from FMA contraction). Dispatch
4391
+ // ceil(out_groups / 2) in z (see conv2d.ts).
3814
4392
  //
3815
4393
  // Tensor layout: NHWC, channels in vec4 groups (same as conv2d.wgsl).
3816
4394
  // Weight layout: [K*K][out_groups][in_groups] array of mat4x4 (same as conv2d.wgsl).
@@ -3827,7 +4405,7 @@ struct Params {
3827
4405
  stride : u32,
3828
4406
  pad_top : u32,
3829
4407
  pad_left : u32,
3830
- activation : u32, // 0 = none, 1 = relu6, 2 = relu
4408
+ activation : u32, // 0 = none, 1 = relu6, 2 = relu, 3 = leaky
3831
4409
  }
3832
4410
 
3833
4411
  @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
@@ -3836,18 +4414,19 @@ struct Params {
3836
4414
  @group(0) @binding(3) var<uniform> params : Params;
3837
4415
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
3838
4416
 
3839
- const KB = 4u;
4417
+ const KB = 2u;
3840
4418
 
3841
4419
  fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
3842
4420
  if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
3843
4421
  if (a == 2u) { return max(v, vec4<f32>(0.0)); }
4422
+ if (a == 3u) { return max(v, 0.1 * v); } // leaky relu (slope 0.1)
3844
4423
  return v;
3845
4424
  }
3846
4425
 
3847
4426
  @compute @workgroup_size(8, 8, 1)
3848
4427
  fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3849
- let x = gid.x; // output column
3850
- let y = gid.y; // output row
4428
+ let x = gid.x; // output column
4429
+ let y = gid.y; // output row
3851
4430
  let o0 = gid.z * KB; // first output channel group
3852
4431
 
3853
4432
  if (x >= params.out_w || y >= params.out_h || o0 >= params.out_groups) {
@@ -3856,19 +4435,13 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3856
4435
 
3857
4436
  let I = params.in_groups;
3858
4437
  let O = params.out_groups;
3859
- // Tail handling when out_groups is not a multiple of 4: clamp the spare lanes
3860
- // to o0 (valid index, no OOB) and just don't write them.
4438
+ // Tail handling when out_groups is odd: clamp the spare lane to o0 (valid
4439
+ // index, no OOB) and just don't write it.
3861
4440
  let has1 = (o0 + 1u) < O;
3862
- let has2 = (o0 + 2u) < O;
3863
- let has3 = (o0 + 3u) < O;
3864
4441
  let o1 = select(o0, o0 + 1u, has1);
3865
- let o2 = select(o0, o0 + 2u, has2);
3866
- let o3 = select(o0, o0 + 3u, has3);
3867
4442
 
3868
4443
  var acc0 = bias_buf[o0];
3869
4444
  var acc1 = bias_buf[o1];
3870
- var acc2 = bias_buf[o2];
3871
- var acc3 = bias_buf[o3];
3872
4445
 
3873
4446
  for (var ky = 0u; ky < params.kernel_h; ky++) {
3874
4447
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -3884,14 +4457,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3884
4457
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
3885
4458
  let wb0 = z * O * I + o0 * I;
3886
4459
  let wb1 = z * O * I + o1 * I;
3887
- let wb2 = z * O * I + o2 * I;
3888
- let wb3 = z * O * I + o3 * I;
3889
4460
  for (var i = 0u; i < I; i++) {
3890
- let iv = input_buf[inB + i]; // loaded ONCE, reused across 4 groups
4461
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
3891
4462
  acc0 += weight_buf[wb0 + i] * iv;
3892
4463
  acc1 += weight_buf[wb1 + i] * iv;
3893
- acc2 += weight_buf[wb2 + i] * iv;
3894
- acc3 += weight_buf[wb3 + i] * iv;
3895
4464
  }
3896
4465
  }
3897
4466
  }
@@ -3899,15 +4468,14 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3899
4468
  let baseO = y * params.out_w * O + x * O;
3900
4469
  output_buf[baseO + o0] = act(acc0, params.activation);
3901
4470
  if (has1) { output_buf[baseO + o1] = act(acc1, params.activation); }
3902
- if (has2) { output_buf[baseO + o2] = act(acc2, params.activation); }
3903
- if (has3) { output_buf[baseO + o3] = act(acc3, params.activation); }
3904
4471
  }
3905
- `;var Oe=`enable f16;
4472
+ `;var Qe=`enable f16;
3906
4473
 
3907
- // Conv2d, output-channel-blocked (K=4) \u2014 full f16. Drop-in replacement for
3908
- // conv2d_f16.wgsl. Each thread computes 4 output channel-groups for one pixel,
3909
- // loading each input vec4 once and reusing it across all four weight blocks.
3910
- // Output is bit-identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 4) in z.
4474
+ // Conv2d, output-channel-blocked (K=2) \u2014 full f16. Drop-in replacement for
4475
+ // conv2d_f16.wgsl. Each thread computes 2 output channel-groups for one pixel,
4476
+ // loading each input vec4 ONCE and reusing it across both weight blocks. Half the
4477
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
4478
+ // identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 2) in z.
3911
4479
 
3912
4480
  struct Params {
3913
4481
  in_h : u32,
@@ -3930,11 +4498,12 @@ struct Params {
3930
4498
  @group(0) @binding(3) var<uniform> params : Params;
3931
4499
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
3932
4500
 
3933
- const KB = 4u;
4501
+ const KB = 2u;
3934
4502
 
3935
4503
  fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
3936
4504
  if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
3937
4505
  if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
4506
+ if (a == 3u) { return max(v, 0.1h * v); } // leaky relu (slope 0.1)
3938
4507
  return v;
3939
4508
  }
3940
4509
 
@@ -3951,16 +4520,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3951
4520
  let I = params.in_groups;
3952
4521
  let O = params.out_groups;
3953
4522
  let has1 = (o0 + 1u) < O;
3954
- let has2 = (o0 + 2u) < O;
3955
- let has3 = (o0 + 3u) < O;
3956
4523
  let o1 = select(o0, o0 + 1u, has1);
3957
- let o2 = select(o0, o0 + 2u, has2);
3958
- let o3 = select(o0, o0 + 3u, has3);
3959
4524
 
3960
4525
  var acc0 = bias_buf[o0];
3961
4526
  var acc1 = bias_buf[o1];
3962
- var acc2 = bias_buf[o2];
3963
- var acc3 = bias_buf[o3];
3964
4527
 
3965
4528
  for (var ky = 0u; ky < params.kernel_h; ky++) {
3966
4529
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -3976,14 +4539,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3976
4539
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
3977
4540
  let wb0 = z * O * I + o0 * I;
3978
4541
  let wb1 = z * O * I + o1 * I;
3979
- let wb2 = z * O * I + o2 * I;
3980
- let wb3 = z * O * I + o3 * I;
3981
4542
  for (var i = 0u; i < I; i++) {
3982
- let iv = input_buf[inB + i];
4543
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
3983
4544
  acc0 += weight_buf[wb0 + i] * iv;
3984
4545
  acc1 += weight_buf[wb1 + i] * iv;
3985
- acc2 += weight_buf[wb2 + i] * iv;
3986
- acc3 += weight_buf[wb3 + i] * iv;
3987
4546
  }
3988
4547
  }
3989
4548
  }
@@ -3991,10 +4550,156 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3991
4550
  let baseO = y * params.out_w * O + x * O;
3992
4551
  output_buf[baseO + o0] = act(acc0, params.activation);
3993
4552
  if (has1) { output_buf[baseO + o1] = act(acc1, params.activation); }
3994
- if (has2) { output_buf[baseO + o2] = act(acc2, params.activation); }
3995
- if (has3) { output_buf[baseO + o3] = act(acc3, params.activation); }
3996
4553
  }
3997
- `;function _(a,t,e,r){return typeof r=="number"?Math.floor((a+2*r-t)/e)+1:r==="same"?Math.ceil(a/e):Math.floor((a-t)/e)+1}function ir(a,t,e,r){return Math.floor(Math.max((t-1)*r+e-a,0)/2)}function m(a,t,e,r,n){return typeof a=="number"?a:a==="same"?ir(t,e,r,n):0}function d(a){return a instanceof Float32Array||a instanceof Uint16Array?a:new Float32Array(a)}function g(a){let t=Math.max(4,Math.ceil(a.length/4)*4),e=new Float32Array(t);for(let r=0;r<a.length;r++)e[r]=a[r];return e}var M=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Oe:Ae;let i=_(e.h,n.kernel,n.stride,n.padding),o=_(e.w,n.kernel,n.stride,n.padding),u=e.c/4,s=n.outChannels/4,l=m(n.padding,e.h,i,n.kernel,n.stride),c=m(n.padding,e.w,o,n.kernel,n.stride);this.output=t.tensor(i,o,n.outChannels),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i,o,u,s,n.kernel,n.kernel,n.stride,l,c,n.activation==="relu6"?1:n.activation==="relu"?2:0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/8),Math.ceil(i/8),Math.ceil(s/4)];}};var Me=`// Depthwise Conv2d \u2014 groups = in_channels (each channel convolved independently).
4554
+ `;function _(a,t,e,r){return typeof r=="number"?Math.floor((a+2*r-t)/e)+1:r==="same"?Math.ceil(a/e):Math.floor((a-t)/e)+1}function Pe(a,t,e,r){return (a-1)*e-2*r+t}function zr(a,t,e,r){return Math.floor(Math.max((t-1)*r+e-a,0)/2)}function b(a,t,e,r,n){return typeof a=="number"?a:a==="same"?zr(t,e,r,n):0}function d(a){return a instanceof Float32Array||a instanceof Uint16Array?a:new Float32Array(a)}function g(a){let t=Math.max(4,Math.ceil(a.length/4)*4),e=new Float32Array(t),r=a instanceof Uint16Array;for(let n=0;n<a.length;n++)e[n]=r?ye(a[n]):a[n];return e}var R=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Qe:Je;let i=_(e.h,n.kernel,n.stride,n.padding),o=_(e.w,n.kernel,n.stride,n.padding),s=e.c/4,u=n.outChannels/4,l=b(n.padding,e.h,i,n.kernel,n.stride),c=b(n.padding,e.w,o,n.kernel,n.stride);this.output=t.tensor(i,o,n.outChannels),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i,o,s,u,n.kernel,n.kernel,n.stride,l,c,n.activation==="relu6"?1:n.activation==="relu"?2:n.activation==="leaky"?3:0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/8),Math.ceil(i/8),Math.ceil(u/2)];}};var Ze=`// ConvTranspose2d \u2014 gather form, f32 variant. See conv_transpose2d_f16.wgsl for
4555
+ // the math; this is the f32 storage build (mat4x4<f32>).
4556
+
4557
+ struct Params {
4558
+ in_h : u32,
4559
+ in_w : u32,
4560
+ out_h : u32,
4561
+ out_w : u32,
4562
+ in_groups : u32,
4563
+ out_groups : u32,
4564
+ kernel_h : u32,
4565
+ kernel_w : u32,
4566
+ stride : u32,
4567
+ pad_top : u32,
4568
+ pad_left : u32,
4569
+ activation : u32,
4570
+ }
4571
+
4572
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
4573
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f32>>;
4574
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f32>>;
4575
+ @group(0) @binding(3) var<uniform> params : Params;
4576
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
4577
+
4578
+ fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
4579
+ if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
4580
+ if (a == 2u) { return max(v, vec4<f32>(0.0)); }
4581
+ if (a == 3u) { return max(v, 0.1 * v); }
4582
+ return v;
4583
+ }
4584
+
4585
+ @compute @workgroup_size(8, 8, 1)
4586
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4587
+ let ox = gid.x;
4588
+ let oy = gid.y;
4589
+ let o = gid.z;
4590
+
4591
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
4592
+ return;
4593
+ }
4594
+
4595
+ let I = params.in_groups;
4596
+ let O = params.out_groups;
4597
+ let s = i32(params.stride);
4598
+
4599
+ var result = bias_buf[o];
4600
+
4601
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
4602
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
4603
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
4604
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
4605
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
4606
+ continue;
4607
+ }
4608
+ let iy = iy_num / s;
4609
+ let ix = ix_num / s;
4610
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
4611
+ continue;
4612
+ }
4613
+
4614
+ let z = ky * params.kernel_w + kx;
4615
+ for (var i = 0u; i < I; i++) {
4616
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
4617
+ let w_idx = z * O * I + o * I + i;
4618
+ result += weight_buf[w_idx] * input_buf[in_idx];
4619
+ }
4620
+ }
4621
+ }
4622
+
4623
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
4624
+ }
4625
+ `;var et=`enable f16;
4626
+
4627
+ // ConvTranspose2d \u2014 gather form, full f16 variant.
4628
+ // Each output (oy,ox) sums every input pixel + kernel tap that maps onto it:
4629
+ // iy = (oy + pad - ky) / stride (must divide evenly and be in bounds)
4630
+ // No explicit kernel flip \u2014 the (oy + pad - ky) indexing carries it.
4631
+ // Weight layout is IDENTICAL to conv2d (mat4x4[z][o][i], M[in_sub][out_sub] =
4632
+ // W(in, out, ky, kx)), so the op uploads the flat buffer unchanged.
4633
+
4634
+ struct Params {
4635
+ in_h : u32,
4636
+ in_w : u32,
4637
+ out_h : u32,
4638
+ out_w : u32,
4639
+ in_groups : u32,
4640
+ out_groups : u32,
4641
+ kernel_h : u32,
4642
+ kernel_w : u32,
4643
+ stride : u32,
4644
+ pad_top : u32,
4645
+ pad_left : u32,
4646
+ activation : u32,
4647
+ }
4648
+
4649
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
4650
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f16>>;
4651
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f16>>;
4652
+ @group(0) @binding(3) var<uniform> params : Params;
4653
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
4654
+
4655
+ fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
4656
+ if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
4657
+ if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
4658
+ if (a == 3u) { return max(v, 0.1h * v); }
4659
+ return v;
4660
+ }
4661
+
4662
+ @compute @workgroup_size(8, 8, 1)
4663
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4664
+ let ox = gid.x;
4665
+ let oy = gid.y;
4666
+ let o = gid.z;
4667
+
4668
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
4669
+ return;
4670
+ }
4671
+
4672
+ let I = params.in_groups;
4673
+ let O = params.out_groups;
4674
+ let s = i32(params.stride);
4675
+
4676
+ var result = bias_buf[o];
4677
+
4678
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
4679
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
4680
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
4681
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
4682
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
4683
+ continue;
4684
+ }
4685
+ let iy = iy_num / s;
4686
+ let ix = ix_num / s;
4687
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
4688
+ continue;
4689
+ }
4690
+
4691
+ let z = ky * params.kernel_w + kx;
4692
+ for (var i = 0u; i < I; i++) {
4693
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
4694
+ let w_idx = z * O * I + o * I + i;
4695
+ result += weight_buf[w_idx] * input_buf[in_idx];
4696
+ }
4697
+ }
4698
+ }
4699
+
4700
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
4701
+ }
4702
+ `;var H=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?et:Ze;let i=Pe(e.h,n.kernel,n.stride,n.padding),o=Pe(e.w,n.kernel,n.stride,n.padding),s=e.c/4,u=n.outChannels/4;this.output=t.tensor(i,o,n.outChannels),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i,o,s,u,n.kernel,n.kernel,n.stride,n.padding,n.padding,n.activation==="relu6"?1:n.activation==="relu"?2:n.activation==="leaky"?3:0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/8),Math.ceil(i/8),u];}};var tt=`// Depthwise Conv2d \u2014 groups = in_channels (each channel convolved independently).
3998
4703
  //
3999
4704
  // Weight layout: [K*K][channel_groups] array of vec4
4000
4705
  // weight index = (ky*kernel_w + kx) * channel_groups + c
@@ -4069,7 +4774,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4069
4774
  let out_idx = y * params.out_w * C + x * C + c;
4070
4775
  output_buf[out_idx] = result;
4071
4776
  }
4072
- `;var ze=`enable f16;
4777
+ `;var rt=`enable f16;
4073
4778
 
4074
4779
  // Depthwise conv2d \u2014 full f16 variant. All buffers f16.
4075
4780
 
@@ -4134,7 +4839,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4134
4839
 
4135
4840
  output_buf[y * params.out_w * C + x * C + c] = result;
4136
4841
  }
4137
- `;var z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?ze:Me;let i=_(e.h,n.kernel,n.stride,n.padding),o=_(e.w,n.kernel,n.stride,n.padding),u=e.c/4,s=m(n.padding,e.h,i,n.kernel,n.stride),l=m(n.padding,e.w,o,n.kernel,n.stride);this.output=t.tensor(i,o,e.c),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i,o,u,n.kernel,n.kernel,n.stride,s,l,n.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/8),Math.ceil(i/8),u];}};var De=`// Element-wise add of two tensors \u2014 used for residual connections in MBConv blocks.
4842
+ `;var L=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?rt:tt;let i=_(e.h,n.kernel,n.stride,n.padding),o=_(e.w,n.kernel,n.stride,n.padding),s=e.c/4,u=b(n.padding,e.h,i,n.kernel,n.stride),l=b(n.padding,e.w,o,n.kernel,n.stride);this.output=t.tensor(i,o,e.c),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,i,o,s,n.kernel,n.kernel,n.stride,u,l,n.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(o/8),Math.ceil(i/8),s];}};var nt=`// Element-wise add of two tensors \u2014 used for residual connections in MBConv blocks.
4138
4843
  // Operates on the flat float buffer directly; layout is irrelevant for a pure element-wise op.
4139
4844
 
4140
4845
  struct Params {
@@ -4155,7 +4860,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4155
4860
  if (idx >= params.size) { return; }
4156
4861
  output[idx] = input_a[idx] + input_b[idx];
4157
4862
  }
4158
- `;var Re=`enable f16;
4863
+ `;var at=`enable f16;
4159
4864
 
4160
4865
  // Element-wise add \u2014 full f16 variant.
4161
4866
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -4178,7 +4883,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4178
4883
  if (idx >= params.size) { return; }
4179
4884
  output[idx] = input_a[idx] + input_b[idx];
4180
4885
  }
4181
- `;var D=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Re:De;let n=e.h*e.w*e.c;this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n/256),1,1];}};var He=`// Element-wise sigmoid: output = 1 / (1 + exp(-x)).
4886
+ `;var V=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?at:nt;let n=e.h*e.w*e.c;this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n/256),1,1];}};var it=`// Element-wise sigmoid: output = 1 / (1 + exp(-x)).
4182
4887
  // Operates on packed vec4 buffers (NHWC layout). exp() and arithmetic are element-wise on vec4.
4183
4888
 
4184
4889
  struct Params {
@@ -4198,7 +4903,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4198
4903
  if (idx >= params.n_groups) { return; }
4199
4904
  output_buf[idx] = 1.0 / (1.0 + exp(-input_buf[idx]));
4200
4905
  }
4201
- `;var Le=`enable f16;
4906
+ `;var ot=`enable f16;
4202
4907
 
4203
4908
  // Sigmoid \u2014 full f16 variant.
4204
4909
 
@@ -4220,7 +4925,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4220
4925
  let x = vec4<f32>(input_buf[idx]);
4221
4926
  output_buf[idx] = vec4<f16>(1.0 / (1.0 + exp(-x)));
4222
4927
  }
4223
- `;var R=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?Le:He;let r=e.h*e.w*(e.c/4);this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([r,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r/256),1,1];}};var Ve=`// Element-wise tanh \u2014 used by ConvGRU candidate activation.
4928
+ `;var N=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?ot:it;let r=e.h*e.w*(e.c/4);this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([r,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r/256),1,1];}};var st=`// Element-wise tanh \u2014 used by ConvGRU candidate activation.
4224
4929
  // Operates on packed vec4 buffers (NHWC layout). tanh() is element-wise on vec4.
4225
4930
 
4226
4931
  struct Params {
@@ -4240,7 +4945,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4240
4945
  if (idx >= params.n_groups) { return; }
4241
4946
  output_buf[idx] = tanh(input_buf[idx]);
4242
4947
  }
4243
- `;var Ne=`enable f16;
4948
+ `;var ut=`enable f16;
4244
4949
 
4245
4950
  // Tanh \u2014 full f16 variant.
4246
4951
 
@@ -4262,7 +4967,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4262
4967
  let x = vec4<f32>(input_buf[idx]);
4263
4968
  output_buf[idx] = vec4<f16>(tanh(x));
4264
4969
  }
4265
- `;var H=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?Ne:Ve;let r=e.h*e.w*(e.c/4);this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([r,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r/256),1,1];}};var $e=`// Element-wise multiply \u2014 used in ConvGRU for r \u2299 h_prev.
4970
+ `;var $=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?ut:st;let r=e.h*e.w*(e.c/4);this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([r,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r/256),1,1];}};var pt=`// Element-wise multiply \u2014 used in ConvGRU for r \u2299 h_prev.
4266
4971
  // Same flat-float layout as add.wgsl.
4267
4972
 
4268
4973
  struct Params {
@@ -4283,7 +4988,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4283
4988
  if (idx >= params.size) { return; }
4284
4989
  output[idx] = input_a[idx] * input_b[idx];
4285
4990
  }
4286
- `;var je=`enable f16;
4991
+ `;var lt=`enable f16;
4287
4992
 
4288
4993
  // Element-wise multiply \u2014 full f16 variant.
4289
4994
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -4306,7 +5011,208 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4306
5011
  if (idx >= params.size) { return; }
4307
5012
  output[idx] = input_a[idx] * input_b[idx];
4308
5013
  }
4309
- `;var L=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?je:$e;let n=e.h*e.w*e.c;this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n/256),1,1];}};var qe=`// Bilinear upsample (arbitrary ratio), align_corners=False (matches PyTorch default).
5014
+ `;var j=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?lt:pt;let n=e.h*e.w*e.c;this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n/256),1,1];}};var ct=`// Bilinear gather-warp (f32). See warp_f16.wgsl for the math.
5015
+
5016
+ struct Params {
5017
+ h : u32,
5018
+ w : u32,
5019
+ flow_scale : f32,
5020
+ }
5021
+
5022
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f32>>;
5023
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f32>>;
5024
+ @group(0) @binding(2) var<uniform> params : Params;
5025
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f32>>;
5026
+
5027
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
5028
+ let cx = clamp(x, 0, W - 1);
5029
+ let cy = clamp(y, 0, H - 1);
5030
+ return source_buf[u32(cy) * u32(W) + u32(cx)];
5031
+ }
5032
+
5033
+ @compute @workgroup_size(8, 8, 1)
5034
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5035
+ let x = gid.x;
5036
+ let y = gid.y;
5037
+ if (x >= params.w || y >= params.h) { return; }
5038
+
5039
+ let W = i32(params.w);
5040
+ let H = i32(params.h);
5041
+ let idx = y * params.w + x;
5042
+
5043
+ let f = flow_buf[idx].xy;
5044
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
5045
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
5046
+
5047
+ let x0 = i32(floor(sx));
5048
+ let y0 = i32(floor(sy));
5049
+ let tx = sx - f32(x0);
5050
+ let ty = sy - f32(y0);
5051
+
5052
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
5053
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
5054
+ output_buf[idx] = mix(top, bot, ty);
5055
+ }
5056
+ `;var dt=`enable f16;
5057
+
5058
+ // Bilinear gather-warp (f16 storage, f32 coordinate math). For each output pixel
5059
+ // p, sample the source at p + flow_scale\xB7flow[p].xy and bilinearly interpolate,
5060
+ // clamping the sample to the edge (border-replicate). Source + flow are 4-ch
5061
+ // (1 group), same resolution; flow vector is in .xy.
5062
+
5063
+ struct Params {
5064
+ h : u32,
5065
+ w : u32,
5066
+ flow_scale : f32,
5067
+ }
5068
+
5069
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f16>>;
5070
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f16>>;
5071
+ @group(0) @binding(2) var<uniform> params : Params;
5072
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f16>>;
5073
+
5074
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
5075
+ let cx = clamp(x, 0, W - 1);
5076
+ let cy = clamp(y, 0, H - 1);
5077
+ return vec4<f32>(source_buf[u32(cy) * u32(W) + u32(cx)]);
5078
+ }
5079
+
5080
+ @compute @workgroup_size(8, 8, 1)
5081
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5082
+ let x = gid.x;
5083
+ let y = gid.y;
5084
+ if (x >= params.w || y >= params.h) { return; }
5085
+
5086
+ let W = i32(params.w);
5087
+ let H = i32(params.h);
5088
+ let idx = y * params.w + x;
5089
+
5090
+ let f = vec2<f32>(flow_buf[idx].xy);
5091
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
5092
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
5093
+
5094
+ let x0 = i32(floor(sx));
5095
+ let y0 = i32(floor(sy));
5096
+ let tx = sx - f32(x0);
5097
+ let ty = sy - f32(y0);
5098
+
5099
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
5100
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
5101
+ output_buf[idx] = vec4<f16>(mix(top, bot, ty));
5102
+ }
5103
+ `;var q=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?dt:ct,this.output=t.tensor(e.h,e.w,e.c),this.inputs=[e,r],this.createUniform("params","Params");let i=new Uint32Array(3);i[0]=e.h,i[1]=e.w,new Float32Array(i.buffer)[2]=n.flowScale,this.setUniform("params",i),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var ft=`// Flow-gated temporal stabilizer (f32). See stabilize_f16.wgsl for the math.
5104
+
5105
+ struct Params {
5106
+ h : u32,
5107
+ w : u32,
5108
+ t_lo : f32,
5109
+ t_hi : f32,
5110
+ leak : f32,
5111
+ release : f32,
5112
+ t_div : f32,
5113
+ div_scale: f32,
5114
+ step_x : u32,
5115
+ step_y : u32,
5116
+ }
5117
+
5118
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f32>>;
5119
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f32>>;
5120
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f32>>;
5121
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f32>>;
5122
+ @group(0) @binding(4) var<uniform> params : Params;
5123
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f32>>;
5124
+
5125
+ @compute @workgroup_size(8, 8, 1)
5126
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5127
+ let x = gid.x;
5128
+ let y = gid.y;
5129
+ if (x >= params.w || y >= params.h) { return; }
5130
+ let idx = y * params.w + x;
5131
+
5132
+ let mag = length(flow_buf[idx].xy);
5133
+ let env_prev = env_prev_buf[idx].y;
5134
+ let env = max(mag, params.release * env_prev);
5135
+
5136
+ let xr = min(x + params.step_x, params.w - 1u);
5137
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
5138
+ let yd = min(y + params.step_y, params.h - 1u);
5139
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
5140
+ let dfx = flow_buf[y * params.w + xr].x - flow_buf[y * params.w + xl].x;
5141
+ let dfy = flow_buf[yd * params.w + x].y - flow_buf[yu * params.w + x].y;
5142
+ let divg = abs(dfx + dfy);
5143
+
5144
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
5145
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
5146
+ let g = max(max(g_mag, g_div), params.leak);
5147
+
5148
+ let pred = pred_buf[idx].x;
5149
+ let refv = ref_buf[idx].x;
5150
+ let stab = g * pred + (1.0 - g) * refv;
5151
+
5152
+ output_buf[idx] = vec4<f32>(stab, env, 0.0, 0.0);
5153
+ }
5154
+ `;var ht=`enable f16;
5155
+
5156
+ // Flow-gated temporal stabilizer (f16 storage, f32 gate math). Per pixel:
5157
+ // env = max(|flow.xy|, release\xB7envPrev.y) peak-hold (fast attack, slow release)
5158
+ // div = |\u2202fx/\u2202x + \u2202fy/\u2202y| flow divergence (occlusion seam)
5159
+ // g = max(clamp((env-tLo)/(tHi-tLo),0,1), clamp((div-tDiv)/divScale,0,1), leak)
5160
+ // out = vec4((g\xB7pred + (1-g)\xB7ref).x, env, 0, 0)
5161
+ // The divergence term opens the gate at occlusion/disocclusion boundaries (where
5162
+ // the flow tears but the revealed-background magnitude is ~0). Finite-difference
5163
+ // step spans ~1 base/4 pixel. alpha is in .x of pred/ref; env threads via .y.
5164
+
5165
+ struct Params {
5166
+ h : u32,
5167
+ w : u32,
5168
+ t_lo : f32,
5169
+ t_hi : f32,
5170
+ leak : f32,
5171
+ release : f32,
5172
+ t_div : f32,
5173
+ div_scale: f32,
5174
+ step_x : u32,
5175
+ step_y : u32,
5176
+ }
5177
+
5178
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f16>>;
5179
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f16>>;
5180
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f16>>;
5181
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f16>>;
5182
+ @group(0) @binding(4) var<uniform> params : Params;
5183
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f16>>;
5184
+
5185
+ @compute @workgroup_size(8, 8, 1)
5186
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5187
+ let x = gid.x;
5188
+ let y = gid.y;
5189
+ if (x >= params.w || y >= params.h) { return; }
5190
+ let idx = y * params.w + x;
5191
+
5192
+ let mag = length(vec2<f32>(flow_buf[idx].xy));
5193
+ let env_prev = f32(env_prev_buf[idx].y);
5194
+ let env = max(mag, params.release * env_prev);
5195
+
5196
+ // Flow divergence over a \xB1step finite-difference (clamped to the edges).
5197
+ let xr = min(x + params.step_x, params.w - 1u);
5198
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
5199
+ let yd = min(y + params.step_y, params.h - 1u);
5200
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
5201
+ let dfx = f32(flow_buf[y * params.w + xr].x) - f32(flow_buf[y * params.w + xl].x);
5202
+ let dfy = f32(flow_buf[yd * params.w + x].y) - f32(flow_buf[yu * params.w + x].y);
5203
+ let divg = abs(dfx + dfy);
5204
+
5205
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
5206
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
5207
+ let g = max(max(g_mag, g_div), params.leak);
5208
+
5209
+ let pred = f32(pred_buf[idx].x);
5210
+ let refv = f32(ref_buf[idx].x);
5211
+ let stab = g * pred + (1.0 - g) * refv;
5212
+
5213
+ output_buf[idx] = vec4<f16>(f16(stab), f16(env), 0.0h, 0.0h);
5214
+ }
5215
+ `;var X=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n,i,o){super(t),this.shader=t.dtype==="f16"?ht:ft,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r,n,i],this.createUniform("params","Params");let s=new Uint32Array(10);s[0]=e.h,s[1]=e.w;let u=new Float32Array(s.buffer);u[2]=o.tLo,u[3]=o.tHi,u[4]=o.leak,u[5]=o.release,u[6]=o.tDiv,u[7]=o.divScale,s[8]=o.stepX,s[9]=o.stepY,this.setUniform("params",s),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var gt=`// Bilinear upsample (arbitrary ratio), align_corners=False (matches PyTorch default).
4310
5216
  // Input/output in NHWC vec4 format: index = y*W*(C/4) + x*(C/4) + c_group.
4311
5217
  // Each thread computes one output pixel for one channel group (vec4 = 4 channels).
4312
5218
 
@@ -4364,7 +5270,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4364
5270
 
4365
5271
  output_buf[oy * params.out_w * C + ox * C + c] = result;
4366
5272
  }
4367
- `;var Xe=`enable f16;
5273
+ `;var mt=`enable f16;
4368
5274
 
4369
5275
  // Bilinear upsample 2\xD7 \u2014 full f16 variant.
4370
5276
  // Interpolation weights (wx, wy) and intermediate blends computed in f32 for
@@ -4420,7 +5326,53 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4420
5326
 
4421
5327
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(result);
4422
5328
  }
4423
- `;var V=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Xe:qe;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var Ke=`// Bicubic upsample (arbitrary scale) \u2014 Keys cubic, a=-0.75 (PyTorch default
5329
+ `;var K=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?mt:gt;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var _t=`// Top-left crop (f32). See crop_f16.wgsl.
5330
+
5331
+ struct Params {
5332
+ in_w : u32,
5333
+ out_h : u32,
5334
+ out_w : u32,
5335
+ groups : u32,
5336
+ }
5337
+
5338
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
5339
+ @group(0) @binding(1) var<uniform> params : Params;
5340
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f32>>;
5341
+
5342
+ @compute @workgroup_size(8, 8, 1)
5343
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5344
+ let x = gid.x;
5345
+ let y = gid.y;
5346
+ let g = gid.z;
5347
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
5348
+ let G = params.groups;
5349
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
5350
+ }
5351
+ `;var bt=`enable f16;
5352
+
5353
+ // Top-left crop: output[y,x,g] = input[y,x,g] for y<outH, x<outW (training crop_like).
5354
+
5355
+ struct Params {
5356
+ in_w : u32,
5357
+ out_h : u32,
5358
+ out_w : u32,
5359
+ groups : u32,
5360
+ }
5361
+
5362
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
5363
+ @group(0) @binding(1) var<uniform> params : Params;
5364
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f16>>;
5365
+
5366
+ @compute @workgroup_size(8, 8, 1)
5367
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5368
+ let x = gid.x;
5369
+ let y = gid.y;
5370
+ let g = gid.z;
5371
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
5372
+ let G = params.groups;
5373
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
5374
+ }
5375
+ `;var Y=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?bt:_t;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.w,r.outH,r.outW,n])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var vt=`// Bicubic upsample (arbitrary scale) \u2014 Keys cubic, a=-0.75 (PyTorch default
4424
5376
  // for mode='bicubic', align_corners=False). Direct 2D, 4\xD74 = 16 taps per
4425
5377
  // output pixel. NHWC vec4 layout: index = y*W*(C/4) + x*(C/4) + c_group.
4426
5378
 
@@ -4487,7 +5439,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4487
5439
 
4488
5440
  output_buf[oy * params.out_w * C + ox * C + c] = acc;
4489
5441
  }
4490
- `;var Ye=`enable f16;
5442
+ `;var xt=`enable f16;
4491
5443
 
4492
5444
  // Bicubic upsample \u2014 full f16 storage variant. Bicubic weights and the per-
4493
5445
  // pixel accumulator are computed in f32 (cheap to keep precision around the
@@ -4556,7 +5508,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4556
5508
 
4557
5509
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(acc);
4558
5510
  }
4559
- `;var N=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Ye:Ke;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var Qe=`// Channel concatenation: output = cat(A, B, dim=channel).
5511
+ `;var J=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?xt:vt;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var wt=`// Channel concatenation: output = cat(A, B, dim=channel).
4560
5512
  // Both A and B must share the same H\xD7W and be in NHWC vec4 format.
4561
5513
  // Output layout: for each (y, x), the first a_groups vec4s come from A,
4562
5514
  // followed by b_groups vec4s from B.
@@ -4601,7 +5553,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4601
5553
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
4602
5554
  }
4603
5555
  }
4604
- `;var Je=`enable f16;
5556
+ `;var yt=`enable f16;
4605
5557
 
4606
5558
  // Channel concatenation \u2014 full f16 variant.
4607
5559
 
@@ -4642,7 +5594,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4642
5594
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
4643
5595
  }
4644
5596
  }
4645
- `;var $=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Je:Qe;let n=e.c/4,i=r.c/4,o=n+i;this.output=t.tensor(e.h,e.w,e.c+r.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,i,o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),o];}};var Ze=`// Conv2d + skip add fused.
5597
+ `;var Q=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?yt:wt;let n=e.c/4,i=r.c/4,o=n+i;this.output=t.tensor(e.h,e.w,e.c+r.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,i,o,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),o];}};var kt=`// Conv2d + skip add fused.
4646
5598
  // Identical to conv2d.wgsl except skip is an activation input (binding 1),
4647
5599
  // added element-wise to the conv result at write time.
4648
5600
  // Eliminates the separate add dispatch and its intermediate buffer round-trip.
@@ -4716,7 +5668,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4716
5668
  let out_idx = y * params.out_w * O + x * O + o;
4717
5669
  output_buf[out_idx] = result + skip_buf[out_idx];
4718
5670
  }
4719
- `;var et=`enable f16;
5671
+ `;var Pt=`enable f16;
4720
5672
 
4721
5673
  // Conv2d + skip add fused \u2014 full f16 variant.
4722
5674
 
@@ -4790,7 +5742,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4790
5742
  let out_idx = y * params.out_w * O + x * O + o;
4791
5743
  output_buf[out_idx] = result + skip_buf[out_idx];
4792
5744
  }
4793
- `;var j=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?et:Ze;let o=_(e.h,i.kernel,i.stride,i.padding),u=_(e.w,i.kernel,i.stride,i.padding),s=e.c/4,l=i.outChannels/4,c=m(i.padding,e.h,o,i.kernel,i.stride),h=m(i.padding,e.w,u,i.kernel,i.stride);this.output=t.tensor(o,u,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,u,s,l,i.kernel,i.kernel,i.stride,c,h,i.activation==="relu6"?1:0])),this.defaultSetup(),this.dispatch=[Math.ceil(u/8),Math.ceil(o/8),l];}};var tt=`// proj_residual: bespoke 1\xD71 conv (no activation) + residual add, fused.
5745
+ `;var Z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Pt:kt;let o=_(e.h,i.kernel,i.stride,i.padding),s=_(e.w,i.kernel,i.stride,i.padding),u=e.c/4,l=i.outChannels/4,c=b(i.padding,e.h,o,i.kernel,i.stride),f=b(i.padding,e.w,s,i.kernel,i.stride);this.output=t.tensor(o,s,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,s,u,l,i.kernel,i.kernel,i.stride,c,f,i.activation==="relu6"?1:0])),this.defaultSetup(),this.dispatch=[Math.ceil(s/8),Math.ceil(o/8),l];}};var Ct=`// proj_residual: bespoke 1\xD71 conv (no activation) + residual add, fused.
4794
5746
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation: drops
4795
5747
  // the kernel loop, the padding checks, and the activation branch. Used by the
4796
5748
  // MBConv project+residual tail. Both inputs share the same spatial resolution.
@@ -4835,7 +5787,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4835
5787
 
4836
5788
  output_buf[pix * O + o] = result;
4837
5789
  }
4838
- `;var rt=`enable f16;
5790
+ `;var Tt=`enable f16;
4839
5791
 
4840
5792
  // proj_residual \u2014 full f16 variant. See proj_residual.wgsl for layout details.
4841
5793
  // Bespoke 1\xD71 conv (no activation) + residual add, fused.
@@ -4877,7 +5829,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4877
5829
 
4878
5830
  output_buf[pix * O + o] = result;
4879
5831
  }
4880
- `;var q=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?rt:tt;let o=e.c/4,u=i.outChannels/4;this.output=t.tensor(e.h,e.w,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,u])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),u];}};var nt=`// concat_conv2d: fuses [concat(a, b) \u2192 conv 3\xD73 (pad 1) \u2192 relu6] into one
5832
+ `;var ee=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Tt:Ct;let o=e.c/4,s=i.outChannels/4;this.output=t.tensor(e.h,e.w,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,s])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),s];}};var Ut=`// concat_conv2d: fuses [concat(a, b) \u2192 conv 3\xD73 (pad 1) \u2192 relu6] into one
4881
5833
  // dispatch. Both inputs are already at the output resolution (the upstream
4882
5834
  // upsample stays a separate dispatch writing a clean intermediate, so the conv
4883
5835
  // reads are plain-indexed). Identical math to conv2d; the only difference is
@@ -4937,7 +5889,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4937
5889
  result = clamp(result, vec4<f32>(0.0), vec4<f32>(6.0));
4938
5890
  output_buf[(y * p.w + x) * O + o] = result;
4939
5891
  }
4940
- `;var at=`enable f16;
5892
+ `;var Wt=`enable f16;
4941
5893
 
4942
5894
  // concat_conv2d \u2014 full f16 variant. See concat_conv2d.wgsl for layout details.
4943
5895
  // Fuses [concat(a, b) \u2192 conv 3\xD73 (pad 1) \u2192 relu6] into one dispatch.
@@ -4992,7 +5944,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4992
5944
  result = clamp(result, vec4<f16>(0.0h), vec4<f16>(6.0h));
4993
5945
  output_buf[(y * p.w + x) * O + o] = result;
4994
5946
  }
4995
- `;var X=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?at:nt;let o=e.c/4,u=r.c/4,s=i.outChannels/4;this.output=t.tensor(e.h,e.w,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,u,s,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),s];}};var it=`// gates_fused: ConvGRU z + r gates, fused into one dispatch.
5947
+ `;var te=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Wt:Ut;let o=e.c/4,s=r.c/4,u=i.outChannels/4;this.output=t.tensor(e.h,e.w,i.outChannels),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(d(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,s,u,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),u];}};var It=`// gates_fused: ConvGRU z + r gates, fused into one dispatch.
4996
5948
  // Production config (c_up=2, split_ratio=0.5 \u2192 passthrough=1, recurrent=1):
4997
5949
  // u_in : c_up=2 packed in a vec4 (.x = passthrough a, .y = recurrent b)
4998
5950
  // h_prev : hidden carrier \u2014 recurrent state in .z (see cand_update_fused: the
@@ -5037,7 +5989,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5037
5989
  let r = 1.0 / (1.0 + exp(-r_pre));
5038
5990
  output_buf[y * params.w + x] = vec4<f32>(z, r, 0.0, 0.0);
5039
5991
  }
5040
- `;var ot=`enable f16;
5992
+ `;var Bt=`enable f16;
5041
5993
 
5042
5994
  // gates_fused \u2014 full f16 variant. See gates_fused.wgsl for layout details.
5043
5995
  // ConvGRU z + r gates (production config c_up=2, recurrent=1).
@@ -5079,7 +6031,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5079
6031
  let r = 1.0h / (1.0h + exp(-r_pre));
5080
6032
  output_buf[y * params.w + x] = vec4<f16>(z, r, 0.0h, 0.0h);
5081
6033
  }
5082
- `;var K=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?ot:it,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var ut=`// cand_update_fused: ConvGRU candidate path + state update + output, fused.
6034
+ `;var re=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Bt:It,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var St=`// cand_update_fused: ConvGRU candidate path + state update + output, fused.
5083
6035
  // Production config (c_up=2, recurrent=1):
5084
6036
  // u_in : c_up=2 (.x = a passthrough, .y = b recurrent)
5085
6037
  // h_prev : hidden carrier \u2014 recurrent state in .z (the previous frame's
@@ -5132,7 +6084,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5132
6084
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
5133
6085
  output_buf[cur] = vec4<f32>(u_cur.x, b_out, h_new, 0.0);
5134
6086
  }
5135
- `;var st=`enable f16;
6087
+ `;var Et=`enable f16;
5136
6088
 
5137
6089
  // cand_update_fused \u2014 full f16 variant. See cand_update_fused.wgsl for details.
5138
6090
  // ConvGRU candidate + state update + output (production config c_up=2, recurrent=1).
@@ -5178,7 +6130,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5178
6130
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
5179
6131
  output_buf[cur] = vec4<f16>(u_cur.x, b_out, h_new, 0.0h);
5180
6132
  }
5181
- `;var Y=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i,o){super(t),this.shader=t.dtype==="f16"?st:ut,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r,n],this.weights=[t.upload(d(i.weights)),t.upload(g(i.bias)),t.upload(g(o))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var pt=`// conv_expand: bespoke N\u21922 conv 3\xD73 (pad 1) + relu (wrapper expand_feat).
6133
+ `;var ne=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i,o){super(t),this.shader=t.dtype==="f16"?Et:St,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r,n],this.weights=[t.upload(d(i.weights)),t.upload(g(i.bias)),t.upload(g(o))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var Gt=`// conv_expand: bespoke N\u21922 conv 3\xD73 (pad 1) + relu (wrapper expand_feat).
5182
6134
  // Expands feat_lr (in_c, mult of 4) to the c_up=2 carrier \u2014 output .xy = the 2
5183
6135
  // native channels, .zw = 0. mat4x2 per (kpos, in_group) with a vec2 accumulator.
5184
6136
  // Weight: 9 * in_groups mat4x2 (8 floats each, col-major). Bias .xy.
@@ -5215,7 +6167,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5215
6167
  result = max(result, vec2<f32>(0.0)); // expand_feat is F.relu
5216
6168
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
5217
6169
  }
5218
- `;var lt=`enable f16;
6170
+ `;var Ft=`enable f16;
5219
6171
 
5220
6172
  // conv_expand \u2014 full f16 variant. See conv_expand.wgsl for layout details.
5221
6173
  // Bespoke N\u21922 conv 3\xD73 (pad 1) + relu (wrapper expand_feat).
@@ -5252,7 +6204,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5252
6204
  result = max(result, vec2<f16>(0.0h));
5253
6205
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
5254
6206
  }
5255
- `;var Q=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?lt:pt;let n=e.c/4;this.output=t.tensor(e.h,e.w,4),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(g(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var ct=`// cat_conv_6to2: fused concat(u, d) + 6\u21922 conv 3\xD73 (pad 1) + relu (E up1_combine).
6207
+ `;var ae=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Ft:Gt;let n=e.c/4;this.output=t.tensor(e.h,e.w,4),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(g(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var At=`// cat_conv_6to2: fused concat(u, d) + 6\u21922 conv 3\xD73 (pad 1) + relu (E up1_combine).
5256
6208
  // u = c_up=2 carrier (.xy); d = c_high=4 (full vec4). Both same resolution.
5257
6209
  // Channel order concat([u, d]) = (u.x, u.y, d.x, d.y, d.z, d.w), split into
5258
6210
  // v3a = (u.x, u.y, d.x) v3b = d.yzw
@@ -5292,7 +6244,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5292
6244
  result = max(result, vec2<f32>(0.0)); // up1_combine is F.relu
5293
6245
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
5294
6246
  }
5295
- `;var dt=`enable f16;
6247
+ `;var Mt=`enable f16;
5296
6248
 
5297
6249
  // cat_conv_6to2 \u2014 full f16 variant. See cat_conv_6to2.wgsl for layout details.
5298
6250
  // Fused concat(u, d) + 6\u21922 conv 3\xD73 (pad 1) + relu (E up1_combine).
@@ -5331,7 +6283,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5331
6283
  result = max(result, vec2<f16>(0.0h));
5332
6284
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
5333
6285
  }
5334
- `;var J=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?dt:ct,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var ht=`// down_adapter: fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no
6286
+ `;var ie=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Mt:At,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var Ot=`// down_adapter: fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no
5335
6287
  // act) into one dispatch. E variant: down2 (c_high=4 \u2192 c_low=4, stride 2) +
5336
6288
  // adapter. A/B variant: down1 (RGB .xyz \u2192 4, stride 2/3) + adapter (the down
5337
6289
  // weight's 4th input column is zeroed at export for RGB input). Symmetric pad.
@@ -5379,7 +6331,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5379
6331
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
5380
6332
  output_buf[y * p.out_w + x] = vec4<f32>(adapt_out.xyz, 0.0);
5381
6333
  }
5382
- `;var ft=`enable f16;
6334
+ `;var Dt=`enable f16;
5383
6335
 
5384
6336
  // down_adapter \u2014 full f16 variant. See down_adapter.wgsl for layout details.
5385
6337
  // Fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no act).
@@ -5424,7 +6376,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5424
6376
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
5425
6377
  output_buf[y * p.out_w + x] = vec4<f16>(adapt_out.xyz, 0.0h);
5426
6378
  }
5427
- `;var Z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?ft:ht;let o=_(e.h,3,i.stride,1),u=_(e.w,3,i.stride,1),s=m(1,e.h,o,3,i.stride),l=m(1,e.w,u,3,i.stride);this.output=t.tensor(o,u,4),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(g(r.bias)),t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,u,i.stride,s,l,0])),this.defaultSetup(),this.dispatch=[Math.ceil(u/8),Math.ceil(o/8),1];}};var gt=`// up_final: fused concat(u, rgb) \u2192 conv 3\xD73 5\u21921 \u2192 sigmoid (A/B alpha head).
6379
+ `;var oe=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Dt:Ot;let o=_(e.h,3,i.stride,1),s=_(e.w,3,i.stride,1),u=b(1,e.h,o,3,i.stride),l=b(1,e.w,s,3,i.stride);this.output=t.tensor(o,s,4),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(g(r.bias)),t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,s,i.stride,u,l,0])),this.defaultSetup(),this.dispatch=[Math.ceil(s/8),Math.ceil(o/8),1];}};var zt=`// up_final: fused concat(u, rgb) \u2192 conv 3\xD73 5\u21921 \u2192 sigmoid (A/B alpha head).
5428
6380
  // u = c_up=2 carrier (.xy); rgb = x_hr (.xyz). 5 inputs \u2192 1 alpha (output .x).
5429
6381
  // Weight: 18 vec4 \u2014 [0..8] = (w0, w1, 0, 0) for u per kpos; [9..17] =
5430
6382
  // (w2, w3, w4, 0) for rgb per kpos. Bias .x.
@@ -5458,7 +6410,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5458
6410
 
5459
6411
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
5460
6412
  }
5461
- `;var _t=`enable f16;
6413
+ `;var Rt=`enable f16;
5462
6414
 
5463
6415
  // up_final \u2014 full f16 variant. See up_final.wgsl for layout details.
5464
6416
  // Fused concat(u, rgb) \u2192 conv 3\xD73 5\u21921 \u2192 sigmoid (A/B alpha head).
@@ -5492,7 +6444,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5492
6444
 
5493
6445
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
5494
6446
  }
5495
- `;var ee=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?_t:gt,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var mt=`// up_final_skip: C/D alpha head. Fused concat(u, d_full, rgb) \u2192 conv 3\xD73 9\u21921
6447
+ `;var se=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Rt:zt,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r],this.weights=[t.upload(d(n.weights)),t.upload(g(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var Ht=`// up_final_skip: C/D alpha head. Fused concat(u, d_full, rgb) \u2192 conv 3\xD73 9\u21921
5496
6448
  // \u2192 sigmoid. u = c_up=2 (.xy); d_full = c_high=4 full-res skip (full vec4);
5497
6449
  // rgb = x_hr (.xyz). Channel order concat = 2 + 4 + 3 = 9. Output .x = alpha.
5498
6450
  // Weight: 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u; [kpos*3+1]=(w2..w5)
@@ -5529,7 +6481,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5529
6481
 
5530
6482
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
5531
6483
  }
5532
- `;var bt=`enable f16;
6484
+ `;var Lt=`enable f16;
5533
6485
 
5534
6486
  // up_final_skip \u2014 full f16 variant. See up_final_skip.wgsl for layout details.
5535
6487
  // C/D alpha head: fused concat(u, d_full, rgb) \u2192 conv 3\xD73 9\u21921 \u2192 sigmoid.
@@ -5565,7 +6517,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5565
6517
 
5566
6518
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
5567
6519
  }
5568
- `;var te=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?bt:mt,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r,n],this.weights=[t.upload(d(i.weights)),t.upload(g(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var vt=`// Bilinear upsample + channel concat fused.
6520
+ `;var ue=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Lt:Ht,this.output=t.tensor(e.h,e.w,4),this.inputs=[e,r,n],this.weights=[t.upload(d(i.weights)),t.upload(g(i.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(e.w/8),Math.ceil(e.h/8),1];}};var Vt=`// Bilinear upsample + channel concat fused.
5569
6521
  // input_a is the decoder tensor at small spatial resolution (in_h \xD7 in_w).
5570
6522
  // input_b is the encoder skip feature already at output resolution (out_h \xD7 out_w).
5571
6523
  // For output channels 0..a_groups-1: bilinearly interpolate from input_a.
@@ -5626,7 +6578,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5626
6578
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
5627
6579
  }
5628
6580
  }
5629
- `;var xt=`enable f16;
6581
+ `;var Nt=`enable f16;
5630
6582
 
5631
6583
  // Bilinear upsample + channel concat fused \u2014 full f16 variant.
5632
6584
  // Bilinear weights (wx, wy) and intermediate blends computed in f32; result cast to f16.
@@ -5686,7 +6638,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5686
6638
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
5687
6639
  }
5688
6640
  }
5689
- `;var re=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?xt:vt;let i=e.c/4,o=r.c/4,u=i+o;this.output=t.tensor(n.outH,n.outW,e.c+r.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n.outH,n.outW,i,o,u,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n.outW/8),Math.ceil(n.outH/8),u];}};var wt=`// Bilinear upsample + 1\xD71 pointwise conv fused.
6641
+ `;var pe=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Nt:Vt;let i=e.c/4,o=r.c/4,s=i+o;this.output=t.tensor(n.outH,n.outW,e.c+r.c),this.inputs=[e,r],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n.outH,n.outW,i,o,s,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n.outW/8),Math.ceil(n.outH/8),s];}};var $t=`// Bilinear upsample + 1\xD71 pointwise conv fused.
5690
6642
  // For each output pixel, bilinearly samples the small input for each in_group,
5691
6643
  // immediately applies the 1\xD71 conv weights, and writes the activated result.
5692
6644
  // Eliminates the intermediate full-resolution upsample buffer.
@@ -5753,7 +6705,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5753
6705
 
5754
6706
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
5755
6707
  }
5756
- `;var yt=`enable f16;
6708
+ `;var jt=`enable f16;
5757
6709
 
5758
6710
  // Bilinear upsample + 1\xD71 pointwise conv fused \u2014 full f16 variant.
5759
6711
  // Bilinear weights and intermediate blends computed in f32; conv accumulation in f16.
@@ -5820,7 +6772,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5820
6772
 
5821
6773
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
5822
6774
  }
5823
- `;var ne=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?yt:wt;let i=e.c/4,o=n.outChannels/4;this.output=t.tensor(n.outH,n.outW,n.outChannels),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n.outH,n.outW,i,o,n.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n.outW/8),Math.ceil(n.outH/8),o];}};var kt=`// Bilinear upsample + sigmoid fused.
6775
+ `;var le=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?jt:$t;let i=e.c/4,o=n.outChannels/4;this.output=t.tensor(n.outH,n.outW,n.outChannels),this.inputs=[e],this.weights=[t.upload(d(r.weights)),t.upload(d(r.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,n.outH,n.outW,i,o,n.activation==="relu6"?1:0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(n.outW/8),Math.ceil(n.outH/8),o];}};var qt=`// Bilinear upsample + sigmoid fused.
5824
6776
  // Identical to bilinear_upsample.wgsl except sigmoid is applied at write time.
5825
6777
  // Eliminates the intermediate full-resolution buffer and the separate sigmoid dispatch.
5826
6778
 
@@ -5874,7 +6826,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5874
6826
 
5875
6827
  output_buf[oy * params.out_w * C + ox * C + c] = 1.0 / (1.0 + exp(-result));
5876
6828
  }
5877
- `;var Ct=`enable f16;
6829
+ `;var Xt=`enable f16;
5878
6830
 
5879
6831
  // Bilinear upsample + sigmoid fused \u2014 full f16 variant.
5880
6832
  // Interpolation computed in f32 for accuracy; sigmoid and result cast to f16.
@@ -5929,7 +6881,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5929
6881
 
5930
6882
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(1.0 / (1.0 + exp(-result)));
5931
6883
  }
5932
- `;var ae=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Ct:kt;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var Pt=`// Composite an RGBA image over a solid background, gated by a 1-ch alpha.
6884
+ `;var ce=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Xt:qt;let n=e.c/4;this.output=t.tensor(r.outH,r.outW,e.c),this.inputs=[e],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,r.outH,r.outW,n,0,0,0])),this.defaultSetup(),this.dispatch=[Math.ceil(r.outW/8),Math.ceil(r.outH/8),n];}};var Kt=`// Composite an RGBA image over a solid background, gated by a 1-ch alpha.
5933
6885
  // Fragment writes the canvas's swapchain texture (premultiplied output).
5934
6886
  //
5935
6887
  // Caller invariants (matched in CompositeSolidWebGPU):
@@ -5974,7 +6926,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
5974
6926
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
5975
6927
  return vec4<f32>(rgb, 1.0);
5976
6928
  }
5977
- `;var Tt=`enable f16;
6929
+ `;var Yt=`enable f16;
5978
6930
 
5979
6931
  // Composite an RGBA image over a solid background, gated by a 1-ch alpha.
5980
6932
  // f16 variant: image and alpha are stored as f16; values promote to f32 on
@@ -6023,7 +6975,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6023
6975
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
6024
6976
  return vec4<f32>(rgb, 1.0);
6025
6977
  }
6026
- `;var ie=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w)throw new Error(`CompositeSolid: image (${e.h}\xD7${e.w}) and alpha (${r.h}\xD7${r.w}) must match. Run the upscaler first.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(32);new Uint32Array(o,0,1)[0]=e.w,new Float32Array(o,16,4).set([n[0],n[1],n[2],0]),i.queue.writeBuffer(this.uniformBuffer,0,o);let u=t.dtype==="f16"?Tt:Pt,s=i.createShaderModule({code:u});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:s,entryPoint:"vs"},fragment:{module:s,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeSolidWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var Ut=`// Like composite_solid but bg is an NHWC vec4 storage buffer (e.g. virtual
6978
+ `;var de=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w)throw new Error(`CompositeSolid: image (${e.h}\xD7${e.w}) and alpha (${r.h}\xD7${r.w}) must match. Run the upscaler first.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(32);new Uint32Array(o,0,1)[0]=e.w,new Float32Array(o,16,4).set([n[0],n[1],n[2],0]),i.queue.writeBuffer(this.uniformBuffer,0,o);let s=t.dtype==="f16"?Yt:Kt,u=i.createShaderModule({code:s});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:u,entryPoint:"vs"},fragment:{module:u,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeSolidWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var Jt=`// Like composite_solid but bg is an NHWC vec4 storage buffer (e.g. virtual
6027
6979
  // background image, or a blurred copy of the input).
6028
6980
 
6029
6981
  struct VertexOut {
@@ -6065,7 +7017,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6065
7017
  let rgb = fg * a + bgc * (1.0 - a);
6066
7018
  return vec4<f32>(rgb, 1.0);
6067
7019
  }
6068
- `;var It=`enable f16;
7020
+ `;var Qt=`enable f16;
6069
7021
 
6070
7022
  // Like composite_solid_f16 but bg is an NHWC vec4<f16> storage buffer (e.g. a
6071
7023
  // virtual background image, or a blurred copy of the input).
@@ -6109,7 +7061,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6109
7061
  let rgb = fg * a + bgc * (1.0 - a);
6110
7062
  return vec4<f32>(rgb, 1.0);
6111
7063
  }
6112
- `;var oe=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w||e.h!==n.h||e.w!==n.w)throw new Error(`CompositeImage: image (${e.h}\xD7${e.w}), alpha (${r.h}\xD7${r.w}), and bg (${n.h}\xD7${n.w}) must all match. Run upscaler / resizer first.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16);new Uint32Array(o,0,1)[0]=e.w,i.queue.writeBuffer(this.uniformBuffer,0,o);let u=t.dtype==="f16"?It:Ut,s=i.createShaderModule({code:u});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:s,entryPoint:"vs"},fragment:{module:s,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:n.buffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeImageWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var Bt=`// Like composite_image but bg is sampled bilinearly \u2014 bg may be smaller than
7064
+ `;var fe=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w||e.h!==n.h||e.w!==n.w)throw new Error(`CompositeImage: image (${e.h}\xD7${e.w}), alpha (${r.h}\xD7${r.w}), and bg (${n.h}\xD7${n.w}) must all match. Run upscaler / resizer first.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16);new Uint32Array(o,0,1)[0]=e.w,i.queue.writeBuffer(this.uniformBuffer,0,o);let s=t.dtype==="f16"?Qt:Jt,u=i.createShaderModule({code:s});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:u,entryPoint:"vs"},fragment:{module:u,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:n.buffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeImageWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var Zt=`// Like composite_image but bg is sampled bilinearly \u2014 bg may be smaller than
6113
7065
  // (image, alpha). Used by CompositorBlur to skip the final full-res upsample
6114
7066
  // in the blur pyramid and let this shader's own per-pixel scan do the
6115
7067
  // expansion (the work is already happening here for the composite anyway).
@@ -6174,7 +7126,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6174
7126
  let rgb = fg * a + bgc * (1.0 - a);
6175
7127
  return vec4<f32>(rgb, 1.0);
6176
7128
  }
6177
- `;var Wt=`enable f16;
7129
+ `;var er=`enable f16;
6178
7130
 
6179
7131
  // f16 storage variant of composite_image_bilinear. bg is at a smaller
6180
7132
  // resolution and is bilinearly sampled to match (image, alpha) at full res.
@@ -6235,7 +7187,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6235
7187
  let rgb = fg * a + bgc * (1.0 - a);
6236
7188
  return vec4<f32>(rgb, 1.0);
6237
7189
  }
6238
- `;var ue=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w)throw new Error(`CompositeImageBilinear: image (${e.h}\xD7${e.w}) and alpha (${r.h}\xD7${r.w}) must match.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16),u=new Uint32Array(o);u[0]=e.w,u[1]=e.h,u[2]=n.w,u[3]=n.h,i.queue.writeBuffer(this.uniformBuffer,0,o);let s=t.dtype==="f16"?Wt:Bt,l=i.createShaderModule({code:s});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:l,entryPoint:"vs"},fragment:{module:l,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:n.buffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeImageBilinearWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var St=`// Passthrough "compositor" \u2014 writes the image directly to the canvas
7190
+ `;var he=class{constructor(t,e,r,n){this.backend=t;if(e.h!==r.h||e.w!==r.w)throw new Error(`CompositeImageBilinear: image (${e.h}\xD7${e.w}) and alpha (${r.h}\xD7${r.w}) must match.`);let i=t.device;this.uniformBuffer=i.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=new ArrayBuffer(16),s=new Uint32Array(o);s[0]=e.w,s[1]=e.h,s[2]=n.w,s[3]=n.h,i.queue.writeBuffer(this.uniformBuffer,0,o);let u=t.dtype==="f16"?er:Zt,l=i.createShaderModule({code:u});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:l,entryPoint:"vs"},fragment:{module:l,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=i.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:r.buffer}},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:n.buffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositeImageBilinearWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var tr=`// Passthrough "compositor" \u2014 writes the image directly to the canvas
6239
7191
  // swapchain texture with no alpha math and no background. Used by RenderOp
6240
7192
  // when the renderer is in disabled state, so the output canvas reflects
6241
7193
  // the unmodified input frame instead of a stale matted result.
@@ -6273,7 +7225,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6273
7225
  let i = y * params.width + x;
6274
7226
  return vec4<f32>(image[i].rgb, 1.0);
6275
7227
  }
6276
- `;var Gt=`enable f16;
7228
+ `;var rr=`enable f16;
6277
7229
 
6278
7230
  // Passthrough "compositor" \u2014 f16 variant. Image is stored as f16; values
6279
7231
  // promote to f32 on read and the fragment writes f32 to the canvas
@@ -6309,7 +7261,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6309
7261
  let i = y * params.width + x;
6310
7262
  return vec4<f32>(vec3<f32>(image[i].rgb), 1.0);
6311
7263
  }
6312
- `;var se=class{constructor(t,e){this.backend=t;let r=t.device;this.uniformBuffer=r.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,1)[0]=e.w,r.queue.writeBuffer(this.uniformBuffer,0,n);let i=t.dtype==="f16"?Gt:St,o=r.createShaderModule({code:i});this.pipeline=r.createRenderPipeline({layout:"auto",vertex:{module:o,entryPoint:"vs"},fragment:{module:o,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=r.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:this.uniformBuffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositePassthroughWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var Et=`// Input op \u2014 sample a regular 2D source texture (RGBA8 unorm) into the NHWC
7264
+ `;var ge=class{constructor(t,e){this.backend=t;let r=t.device;this.uniformBuffer=r.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,1)[0]=e.w,r.queue.writeBuffer(this.uniformBuffer,0,n);let i=t.dtype==="f16"?rr:tr,o=r.createShaderModule({code:i});this.pipeline=r.createRenderPipeline({layout:"auto",vertex:{module:o,entryPoint:"vs"},fragment:{module:o,entryPoint:"fs",targets:[{format:t.canvasFormat}]},primitive:{topology:"triangle-list"}}),this.bindGroup=r.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e.buffer}},{binding:1,resource:{buffer:this.uniformBuffer}}]});}backend;pipeline;bindGroup;uniformBuffer;outputView=null;setOutput(t){this.outputView=t.createView();}run(){if(!this.outputView)throw new Error("CompositePassthroughWebGPU.run() called before setOutput()");let t=this.backend.device.createCommandEncoder(),e=t.beginRenderPass({colorAttachments:[{view:this.outputView,clearValue:[0,0,0,1],loadOp:"clear",storeOp:"store"}]});e.setPipeline(this.pipeline),e.setBindGroup(0,this.bindGroup),e.draw(6),e.end(),this.backend.device.queue.submit([t.finish()]),this.outputView=null;}};var nr=`// Input op \u2014 sample a regular 2D source texture (RGBA8 unorm) into the NHWC
6313
7265
  // vec4<f32> output buffer at the target resolution. Used for ImageBitmap
6314
7266
  // sources, which are uploaded into a persistent staging texture via
6315
7267
  // copyExternalImageToTexture before each dispatch.
@@ -6339,7 +7291,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6339
7291
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
6340
7292
  output_buf[y * params.out_w + x] = rgba;
6341
7293
  }
6342
- `;var Ft=`enable f16;
7294
+ `;var ar=`enable f16;
6343
7295
 
6344
7296
  // Input op \u2014 f16 storage variant. Source is sampled as vec4<f32>; only the
6345
7297
  // store is demoted to vec4<f16>.
@@ -6369,7 +7321,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6369
7321
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
6370
7322
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
6371
7323
  }
6372
- `;var At=`// Input op \u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
7324
+ `;var ir=`// Input op \u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
6373
7325
  // the NHWC vec4<f32> output buffer at the target resolution. Used when the
6374
7326
  // caller passes a VideoFrame to setSource(); requires importExternalTexture
6375
7327
  // to be called in the same task as the dispatch (the texture is invalidated
@@ -6400,7 +7352,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6400
7352
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
6401
7353
  output_buf[y * params.out_w + x] = rgba;
6402
7354
  }
6403
- `;var Ot=`enable f16;
7355
+ `;var or=`enable f16;
6404
7356
 
6405
7357
  // Input op \u2014 texture_external + f16 storage. Sample in f32, store as f16.
6406
7358
 
@@ -6429,4 +7381,4 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6429
7381
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
6430
7382
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
6431
7383
  }
6432
- `;var un=a=>typeof VideoFrame<"u"&&a instanceof VideoFrame,pe=class{output;device;dtype;sampler;uniformBuffer;dispatch;pipeline2d=null;pipelineExternal=null;stagingTex=null;stagingW=0;stagingH=0;source=null;constructor(t,e,r){this.device=t.device,this.dtype=t.dtype,this.output=t.tensor(e,r,4),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,2).set([r,e]),this.device.queue.writeBuffer(this.uniformBuffer,0,n),this.dispatch=[Math.ceil(r/8),Math.ceil(e/8),1],this.pipeline2d=this.buildPipeline(this.dtype==="f16"?Ft:Et);}setSource(t){this.source=t;}run(){if(!this.source)throw new Error("InputWebGPU.run() called before setSource()");un(this.source)?this.runExternal(this.source):this.run2d(this.source);}run2d(t){this.ensureStagingTexture(t.width,t.height),this.device.queue.copyExternalImageToTexture({source:t,flipY:false},{texture:this.stagingTex},[t.width,t.height]);let e=this.device.createBindGroup({layout:this.pipeline2d.getBindGroupLayout(0),entries:[{binding:0,resource:this.stagingTex.createView()},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipeline2d,e);}runExternal(t){this.pipelineExternal||(this.pipelineExternal=this.buildPipeline(this.dtype==="f16"?Ot:At));let e=this.device.importExternalTexture({source:t}),r=this.device.createBindGroup({layout:this.pipelineExternal.getBindGroupLayout(0),entries:[{binding:0,resource:e},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipelineExternal,r);}ensureStagingTexture(t,e){this.stagingTex&&this.stagingW===t&&this.stagingH===e||(this.stagingTex?.destroy(),this.stagingTex=this.device.createTexture({size:[t,e,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.stagingW=t,this.stagingH=e);}buildPipeline(t){let e=this.device.createShaderModule({code:t});return this.device.createComputePipeline({layout:"auto",compute:{module:e,entryPoint:"main"}})}dispatchOnce(t,e){let r=this.device.createCommandEncoder(),n=r.beginComputePass();n.setPipeline(t),n.setBindGroup(0,e),n.dispatchWorkgroups(...this.dispatch),n.end(),this.device.queue.submit([r.finish()]);}};var sn=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,_e=class a{constructor(t,e,r){this.device=t;this.canvas=e;this.dtype=r;this.bytesPerElement=r==="f16"?2:4;let n=e.getContext("webgpu");if(!n)throw new Error("Failed to get WebGPU context from canvas");this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.configureContext(n),this.canvasContext=n,this.contexts.set("main",n),this.ops={Conv2d:(i,o,u)=>new M(this,i,o,u),DepthwiseConv2d:(i,o,u)=>new z(this,i,o,u),Add:(i,o)=>new D(this,i,o),Sigmoid:i=>new R(this,i),Tanh:i=>new H(this,i),ElementwiseMul:(i,o)=>new L(this,i,o),BilinearUpsample:(i,o)=>new V(this,i,o),BicubicUpsample:(i,o)=>new N(this,i,o),ChannelConcat:(i,o)=>new $(this,i,o),Conv2dAdd:(i,o,u,s)=>new j(this,i,o,u,s),ProjResidual:(i,o,u,s)=>new q(this,i,o,u,s),ConcatConv2d:(i,o,u,s)=>new X(this,i,o,u,s),GatesFused:(i,o,u)=>new K(this,i,o,u),CandUpdateFused:(i,o,u,s,l)=>new Y(this,i,o,u,s,l),ConvExpand:(i,o)=>new Q(this,i,o),CatConv6to2:(i,o,u)=>new J(this,i,o,u),DownAdapter:(i,o,u,s)=>new Z(this,i,o,u,s),UpFinal:(i,o,u)=>new ee(this,i,o,u),UpFinalSkip:(i,o,u,s)=>new te(this,i,o,u,s),UpsampleConcat:(i,o,u)=>new re(this,i,o,u),UpsampleConv1x1:(i,o,u)=>new ne(this,i,o,u),UpsampleSigmoid:(i,o)=>new ae(this,i,o),Input:(i,o)=>new pe(this,i,o)},this.presenters={CompositeSolid:(i,o,u,s="main")=>{let l=new ie(this,i,o,u);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(s)),l.run();}}},CompositeImage:(i,o,u,s="main")=>{let l=new oe(this,i,o,u);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(s)),l.run();}}},CompositeImageBilinear:(i,o,u,s="main")=>{let l=new ue(this,i,o,u);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(s)),l.run();}}},CompositePassthrough:(i,o="main")=>{let u=new se(this,i);return {run:()=>{u.setOutput(this.getCurrentDisplayTexture(o)),u.run();}}}};}device;canvas;dtype;ops;presenters;canvasContext;canvasFormat;bytesPerElement;contexts=new Map;configureContext(t){t.configure({device:this.device,format:this.canvasFormat,alphaMode:"premultiplied"});}attachCanvas(t,e){if(t==="main")throw new Error("attachCanvas: 'main' is reserved for the create() canvas");let r=e.getContext("webgpu");if(!r)throw new Error(`attachCanvas: failed to get WebGPU context for target '${t}'`);this.configureContext(r),this.contexts.set(t,r);}static async isAvailable(){return navigator.gpu?await navigator.gpu.requestAdapter()!==null:false}static async hasF16Support(){if(!navigator.gpu)return false;let t=await navigator.gpu.requestAdapter();return t?t.features.has("shader-f16"):false}static async create(t){let e=t.dtype??"f32",r=t.device;if(r){if(e==="f16"&&!r.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but supplied device lacks `shader-f16`")}else {let n=await navigator.gpu.requestAdapter();if(!n)throw new Error("WebGPU adapter not available");if(e==="f16"&&!n.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but adapter lacks `shader-f16` feature");r=await n.requestDevice({requiredFeatures:e==="f16"?["shader-f16"]:[]});}return new a(r,t.canvas,e)}getCurrentDisplayTexture(t="main"){let e=this.contexts.get(t);if(!e)throw new Error(`getCurrentDisplayTexture: no canvas attached for target '${t}'`);return e.getCurrentTexture()}tensor(t,e,r,n){let o=t*e*r*this.bytesPerElement,u=this.device.createBuffer({size:o,usage:sn,mappedAtCreation:n!==void 0});if(n!==void 0){let s=u.getMappedRange();this.writeView(s,n),u.unmap();}return {h:t,w:e,c:r,buffer:u}}upload(t){let r=t.length*this.bytesPerElement,n=this.device.createBuffer({size:r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:true});return this.writeView(n.getMappedRange(),t),n.unmap(),{buffer:n}}writeView(t,e){let r=this.dtype==="f16",n=e instanceof Uint16Array;if(r===n){r?new Uint16Array(t).set(e):new Float32Array(t).set(e);return}r?new Uint16Array(t).set(Fe(e)):new Float32Array(t).set(ge(e));}async readback(t){let e=this.device.createBuffer({size:t.buffer.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(t.buffer,0,e,0,t.buffer.size),this.device.queue.submit([r.finish()]),await e.mapAsync(GPUMapMode.READ);let n=e.getMappedRange(),i=this.dtype==="f16"?ge(new Uint16Array(n.slice(0))):new Float32Array(n.slice(0));return e.unmap(),e.destroy(),i}copyTensor(t,e){if(t.buffer.size!==e.buffer.size)throw new Error(`copyTensor: size mismatch (src ${t.buffer.size} vs dst ${e.buffer.size})`);let r=this.device.createCommandEncoder();r.copyBufferToBuffer(t.buffer,0,e.buffer,0,t.buffer.size),this.device.queue.submit([r.finish()]);}async sync(){await this.device.queue.onSubmittedWorkDone();}destroy(){this.device.destroy();}};export{fe as EffectsPipeline,_e as WebGPUBackend};
7384
+ `;var Kn=a=>typeof VideoFrame<"u"&&a instanceof VideoFrame,me=class{output;device;dtype;sampler;uniformBuffer;dispatch;pipeline2d=null;pipelineExternal=null;stagingTex=null;stagingW=0;stagingH=0;source=null;constructor(t,e,r){this.device=t.device,this.dtype=t.dtype,this.output=t.tensor(e,r,4),this.sampler=this.device.createSampler({magFilter:"linear",minFilter:"linear",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let n=new ArrayBuffer(16);new Uint32Array(n,0,2).set([r,e]),this.device.queue.writeBuffer(this.uniformBuffer,0,n),this.dispatch=[Math.ceil(r/8),Math.ceil(e/8),1],this.pipeline2d=this.buildPipeline(this.dtype==="f16"?ar:nr);}setSource(t){this.source=t;}run(){if(!this.source)throw new Error("InputWebGPU.run() called before setSource()");Kn(this.source)?this.runExternal(this.source):this.run2d(this.source);}run2d(t){this.ensureStagingTexture(t.width,t.height),this.device.queue.copyExternalImageToTexture({source:t,flipY:false},{texture:this.stagingTex},[t.width,t.height]);let e=this.device.createBindGroup({layout:this.pipeline2d.getBindGroupLayout(0),entries:[{binding:0,resource:this.stagingTex.createView()},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipeline2d,e);}runExternal(t){this.pipelineExternal||(this.pipelineExternal=this.buildPipeline(this.dtype==="f16"?or:ir));let e=this.device.importExternalTexture({source:t}),r=this.device.createBindGroup({layout:this.pipelineExternal.getBindGroupLayout(0),entries:[{binding:0,resource:e},{binding:1,resource:this.sampler},{binding:2,resource:{buffer:this.uniformBuffer}},{binding:3,resource:{buffer:this.output.buffer}}]});this.dispatchOnce(this.pipelineExternal,r);}ensureStagingTexture(t,e){this.stagingTex&&this.stagingW===t&&this.stagingH===e||(this.stagingTex?.destroy(),this.stagingTex=this.device.createTexture({size:[t,e,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.stagingW=t,this.stagingH=e);}buildPipeline(t){let e=this.device.createShaderModule({code:t});return this.device.createComputePipeline({layout:"auto",compute:{module:e,entryPoint:"main"}})}dispatchOnce(t,e){let r=this.device.createCommandEncoder(),n=r.beginComputePass();n.setPipeline(t),n.setBindGroup(0,e),n.dispatchWorkgroups(...this.dispatch),n.end(),this.device.queue.submit([r.finish()]);}};var Yn=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,Ce=class a{constructor(t,e,r){this.device=t;this.canvas=e;this.dtype=r;this.bytesPerElement=r==="f16"?2:4;let n=e.getContext("webgpu");if(!n)throw new Error("Failed to get WebGPU context from canvas");this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.configureContext(n),this.canvasContext=n,this.contexts.set("main",n),this.ops={Conv2d:(i,o,s)=>new R(this,i,o,s),ConvTranspose2d:(i,o,s)=>new H(this,i,o,s),DepthwiseConv2d:(i,o,s)=>new L(this,i,o,s),Add:(i,o)=>new V(this,i,o),Sigmoid:i=>new N(this,i),Tanh:i=>new $(this,i),ElementwiseMul:(i,o)=>new j(this,i,o),Warp:(i,o,s)=>new q(this,i,o,s),Stabilize:(i,o,s,u,l)=>new X(this,i,o,s,u,l),BilinearUpsample:(i,o)=>new K(this,i,o),Crop:(i,o)=>new Y(this,i,o),BicubicUpsample:(i,o)=>new J(this,i,o),ChannelConcat:(i,o)=>new Q(this,i,o),Conv2dAdd:(i,o,s,u)=>new Z(this,i,o,s,u),ProjResidual:(i,o,s,u)=>new ee(this,i,o,s,u),ConcatConv2d:(i,o,s,u)=>new te(this,i,o,s,u),GatesFused:(i,o,s)=>new re(this,i,o,s),CandUpdateFused:(i,o,s,u,l)=>new ne(this,i,o,s,u,l),ConvExpand:(i,o)=>new ae(this,i,o),CatConv6to2:(i,o,s)=>new ie(this,i,o,s),DownAdapter:(i,o,s,u)=>new oe(this,i,o,s,u),UpFinal:(i,o,s)=>new se(this,i,o,s),UpFinalSkip:(i,o,s,u)=>new ue(this,i,o,s,u),UpsampleConcat:(i,o,s)=>new pe(this,i,o,s),UpsampleConv1x1:(i,o,s)=>new le(this,i,o,s),UpsampleSigmoid:(i,o)=>new ce(this,i,o),Input:(i,o)=>new me(this,i,o)},this.presenters={CompositeSolid:(i,o,s,u="main")=>{let l=new de(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositeImage:(i,o,s,u="main")=>{let l=new fe(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositeImageBilinear:(i,o,s,u="main")=>{let l=new he(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositePassthrough:(i,o="main")=>{let s=new ge(this,i);return {run:()=>{s.setOutput(this.getCurrentDisplayTexture(o)),s.run();}}}};}device;canvas;dtype;ops;presenters;canvasContext;canvasFormat;bytesPerElement;contexts=new Map;configureContext(t){t.configure({device:this.device,format:this.canvasFormat,alphaMode:"premultiplied"});}attachCanvas(t,e){if(t==="main")throw new Error("attachCanvas: 'main' is reserved for the create() canvas");let r=e.getContext("webgpu");if(!r)throw new Error(`attachCanvas: failed to get WebGPU context for target '${t}'`);this.configureContext(r),this.contexts.set(t,r);}static async isAvailable(){return navigator.gpu?await navigator.gpu.requestAdapter()!==null:false}static async hasF16Support(){if(!navigator.gpu)return false;let t=await navigator.gpu.requestAdapter();return t?t.features.has("shader-f16"):false}static async create(t){let e=t.dtype??"f32",r=t.device;if(r){if(e==="f16"&&!r.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but supplied device lacks `shader-f16`")}else {let n=await navigator.gpu.requestAdapter();if(!n)throw new Error("WebGPU adapter not available");if(e==="f16"&&!n.features.has("shader-f16"))throw new Error("WebGPU dtype='f16' requested but adapter lacks `shader-f16` feature");r=await n.requestDevice({requiredFeatures:e==="f16"?["shader-f16"]:[]});}return new a(r,t.canvas,e)}getCurrentDisplayTexture(t="main"){let e=this.contexts.get(t);if(!e)throw new Error(`getCurrentDisplayTexture: no canvas attached for target '${t}'`);return e.getCurrentTexture()}tensor(t,e,r,n){let o=t*e*r*this.bytesPerElement,s=this.device.createBuffer({size:o,usage:Yn,mappedAtCreation:n!==void 0});if(n!==void 0){let u=s.getMappedRange();this.writeView(u,n),s.unmap();}return {h:t,w:e,c:r,buffer:s}}upload(t){let r=t.length*this.bytesPerElement,n=this.device.createBuffer({size:r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:true});return this.writeView(n.getMappedRange(),t),n.unmap(),{buffer:n}}writeView(t,e){let r=this.dtype==="f16",n=e instanceof Uint16Array;if(r===n){r?new Uint16Array(t).set(e):new Float32Array(t).set(e);return}r?new Uint16Array(t).set(Ye(e)):new Float32Array(t).set(ke(e));}async readback(t){let e=this.device.createBuffer({size:t.buffer.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(t.buffer,0,e,0,t.buffer.size),this.device.queue.submit([r.finish()]),await e.mapAsync(GPUMapMode.READ);let n=e.getMappedRange(),i=this.dtype==="f16"?ke(new Uint16Array(n.slice(0))):new Float32Array(n.slice(0));return e.unmap(),e.destroy(),i}copyTensor(t,e){if(t.buffer.size!==e.buffer.size)throw new Error(`copyTensor: size mismatch (src ${t.buffer.size} vs dst ${e.buffer.size})`);let r=this.device.createCommandEncoder();r.copyBufferToBuffer(t.buffer,0,e.buffer,0,t.buffer.size),this.device.queue.submit([r.finish()]);}async sync(){await this.device.queue.onSubmittedWorkDone();}destroy(){this.device.destroy();}};export{we as EffectsPipeline,Ce as WebGPUBackend};