longpipe 0.0.9 → 0.0.11

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,11 @@
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 le=false;function me(a){le=a;}function x(a){let t=`[longpipe/${a}]`,e=((...r)=>{le&&console.log(t,...r);});return e.warn=(...r)=>{le&&console.warn(t,...r);},e}var P=x("adaptive"),zt=2e3,Mt=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));},zt);}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<Mt)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((l,f)=>{r.addEventListener("loadeddata",()=>l(),{once:true}),r.addEventListener("error",()=>f(new Error(`background video: failed to load ${t}`)),{once:true});});try{await r.play();}catch(l){throw new Error(`background video: play() rejected \u2014 ${l.message}`)}let n=new MessageChannel,i=n.port1,o=n.port2,u=false,s=r.requestVideoFrameCallback?.bind(r);if(s){let l=(f,h)=>{if(!u){try{let v=new VideoFrame(r,{timestamp:h.mediaTime*1e6});i.postMessage({frame:v},[v]);}catch{}s(l);}};s(l);}else {let l=()=>{if(!u){try{let f=new VideoFrame(r,{timestamp:performance.now()*1e3});i.postMessage({frame:f},[f]);}catch{}requestAnimationFrame(l);}};requestAnimationFrame(l);}return {port:o,transferList:[o],cleanup:()=>{u=true,i.close(),r.pause(),r.removeAttribute("src"),r.load(),e&&URL.revokeObjectURL(t);}}}var Nt=4,ce=8,ve=16;async function de(a){if(typeof a=="string")return a==="none"?{background:{kind:"none"}}:a==="blur"?{background:{kind:"blur",sigma:ce}}:{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 ce;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 ce;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 E=null;function Xt(){return E!==null||(E=!/Firefox/.test(navigator.userAgent)),E}function ke(a,t,e){let r=[a];return e==="passthrough"&&r.push(...t.getAudioTracks()),new MediaStream(r)}var F=x("worker_controller"),A=class{worker;listeners=new Map;persistentEvents=new Set;constructor(t){this.worker=t,this.worker.addEventListener("message",this.handleMessage.bind(this)),F("constructed; message listener attached");}handleMessage(t){let{request_id:e,res:r}=t.data,n=this.listeners.get(e);F("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),F("addPersistentListener:",t);}removePersistentListener(t){this.persistentEvents.delete(t),this.listeners.delete(t);}sendMessage(t,e,r=[]){let n=crypto.randomUUID();return F("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(d=>{Ce.warn("video.play() rejected:",d);});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=(d,l)=>{if(!o){try{let f=new VideoFrame(t,{timestamp:l.mediaTime*1e6});n.postMessage({frame:f},[f]);}catch(f){Ce.warn("VideoFrame() failed; skipping frame:",f);}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,d=u.port2,l=false,f=null,h=()=>{},v=3,I=0;return s.onmessage=B=>{if(l){if(I++,I<v){B.data.bmp.close();return}h();}try{r.transferFromImageBitmap(B.data.bmp);}catch(b){Kt.warn("transferFromImageBitmap failed:",b);}},s.start(),{videoTrack:o,port:d,transferList:[d],startPassthrough:B=>{if(l)return;l=true;let b=document.createElement("video");b.srcObject=B,b.muted=true,b.playsInline=true,b.play().catch(()=>{}),f=b;let W="requestVideoFrameCallback"in b?C=>{b.requestVideoFrameCallback(C);}:C=>{requestAnimationFrame(C);},S=()=>{if(l){if(b.videoWidth===0){W(S);return}createImageBitmap(b,{resizeWidth:e.width,resizeHeight:e.height,resizeQuality:"medium"}).then(C=>{if(!l){C.close();return}try{r.transferFromImageBitmap(C);}catch{}W(S);}).catch(()=>{W(S);});}};W(S),h=()=>{l=false,f&&(f.srcObject=null,f.pause(),f=null);};},cleanup:()=>{h(),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 fe=`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){i(this,"presenter");this.presenter=t.presenters.CompositeSolid(r,e,o)}run(){this.presenter.run()}};var j=class{constructor(t,r,e,o){i(this,"presenter");this.presenter=t.presenters.CompositeImage(r,e,o)}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){i(this,"blur");i(this,"presenter");o<=po?(this.blur=null,this.presenter=t.presenters.CompositeImage(r,e,r)):(this.blur=new q(t,r,o),this.presenter=t.presenters.CompositeImageBilinear(r,e,this.blur.output))}run(){this.blur?.run(),this.presenter.run()}};var Y=class{constructor(t){i(this,"backend",t);i(this,"displayInput");i(this,"image");i(this,"passthroughCompositor");i(this,"network",null);i(this,"networkInput",null);i(this,"upscaler",null);i(this,"compositor",null);i(this,"upscalerMode","bilinear");i(this,"bgConfig",{mode:"solid",color:[0,0,0]});let r=t.canvas;this.displayInput=t.ops.Input(r.height,r.width),this.image=this.displayInput.output,this.passthroughCompositor=t.presenters.CompositePassthrough(this.image)}attachNetwork(t,r,e){this.network=t,this.networkInput=r,this.upscalerMode=e.upscaler,this.bgConfig=e.background,this.upscaler=this.makeUpscaler(),this.compositor=this.makeCompositor()}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.compositor=this.makeCompositor()))}setBackground(t){this.bgConfig=t,this.network&&(this.compositor=this.makeCompositor())}run(){this.runModel(),this.runDisplay()}runDisplay(){if(!this.compositor)throw new Error("RenderOp.runDisplay called before attachNetwork");this.displayInput.run(),this.compositor.run()}runPassthrough(){this.displayInput.run(),this.passthroughCompositor.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)}makeCompositor(){if(!this.upscaler)throw new Error("makeCompositor called before upscaler exists");let{backend:t,image:r,upscaler:e,bgConfig:o}=this;switch(o.mode){case"solid":return new X(t,r,e.output,o.color);case"image":return new j(t,r,e.output,o.image);case"blur":return new K(t,r,e.output,o.sigma)}}};var lo=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(lo(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,v;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 W=s.ops.DownAdapter(c,r.down2,r.adapter,{stride:2});l.push(W),v=W.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),v=T.output}else{let y=o==="A"?2:3,T=s.ops.DownAdapter(t,r.down1,r.adapter,{stride:y});l.push(T),v=T.output}return{steps:l,adapted:v,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=[],v=s.ops.ConvExpand(r,u.expandFeat);g.push(v);let y=v.output,T=null;if(l&&p.gruAtBase){let P=new R(s,y,l.hPrev,l.weights);g.push(P),y=P.output,T=P.output}let W;if(m){if(!u.up1Combine)throw new Error("two-stage variant requires w.up1Combine");let P=s.ops.BilinearUpsample(y,{outH:a,outW:n});g.push(P);let ut=s.ops.CatConv6to2(P.output,e,u.up1Combine);g.push(ut);let pt=s.ops.BilinearUpsample(ut.output,{outH:t.h,outW:t.w});g.push(pt),W=pt.output}else{let P=s.ops.BilinearUpsample(y,{outH:t.h,outW:t.w});g.push(P),W=P.output}if(l&&!p.gruAtBase){let P=new R(s,W,l.hPrev,l.weights);g.push(P),W=P.output,T=P.output}let z=_?s.ops.UpFinalSkip(W,o,t,u.upCombine):s.ops.UpFinal(W,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 x=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 G=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 x(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new x(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new x(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new x(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new x(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new x(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new x(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new x(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new x(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new x(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.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 x(t,this.s0.output,e.encoder.s1[0],{inChannels:16,midChannels:96,outChannels:24,kernel:3,stride:2,padding:"same"}),this.s1b1=new x(t,this.s1b0.output,e.encoder.s1[1],{inChannels:24,midChannels:144,outChannels:24,kernel:3,stride:1,padding:1}),this.s2b0=new x(t,this.s1b1.output,e.encoder.s2[0],{inChannels:24,midChannels:144,outChannels:40,kernel:5,stride:2,padding:"same"}),this.s2b1=new x(t,this.s2b0.output,e.encoder.s2[1],{inChannels:40,midChannels:240,outChannels:40,kernel:5,stride:1,padding:2}),this.s3b0=new x(t,this.s2b1.output,e.encoder.s3[0],{inChannels:40,midChannels:240,outChannels:80,kernel:3,stride:2,padding:"same"}),this.s3b1=new x(t,this.s3b0.output,e.encoder.s3[1],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s3b2=new x(t,this.s3b1.output,e.encoder.s3[2],{inChannels:80,midChannels:480,outChannels:80,kernel:3,stride:1,padding:1}),this.s4b0=new x(t,this.s3b2.output,e.encoder.s4[0],{inChannels:80,midChannels:480,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b1=new x(t,this.s4b0.output,e.encoder.s4[1],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s4b2=new x(t,this.s4b1.output,e.encoder.s4[2],{inChannels:112,midChannels:672,outChannels:112,kernel:5,stride:1,padding:2}),this.s5b0=new x(t,this.s4b2.output,e.encoder.s5[0],{inChannels:112,midChannels:672,outChannels:192,kernel:5,stride:2,padding:"same"}),this.s5b1=new x(t,this.s5b0.output,e.encoder.s5[1],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b2=new x(t,this.s5b1.output,e.encoder.s5[2],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s5b3=new x(t,this.s5b2.output,e.encoder.s5[3],{inChannels:192,midChannels:1152,outChannels:192,kernel:5,stride:1,padding:2}),this.s6b0=new x(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.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 v=nt[m][g],y=new x(t,a,o[m][g],{inChannels:v.in,midChannels:v.mid,outChannels:v.out,kernel:v.k,stride:v.s,padding:v.s===2?"same":(v.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 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,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,co=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:co,wrapper:{variant:"E",cHigh:4,cLow:4,cUp:2,gruAtBase:!0},hasGru:!0,canvasRes:{w:1280,h:720},baseRes:{w:320,h:180}}};var mo=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,"bgImageInput",null);i(this,"bgVideoInput",null);i(this,"bgVideoPort",null);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){if(this.renderOp.setSource(t),!this.enabled||this.currentBackground.kind==="none"||!this.renderOp.hasNetwork()){this.renderOp.runPassthrough(),this.framesRenderedAt.push(performance.now()),this.trim(this.framesRenderedAt);return}if(this.shouldRunModel()){let e=performance.now();this.renderOp.runModel(),this.hPrev&&this.tierModel?.hiddenState&&this.backend.copyTensor(this.tierModel.hiddenState,this.hPrev),this.backendKind==="webgpu"&&this.modelTimingCounter%mo===0&&this.backend.sync().then(()=>{this.modelRunSamples.push({ts:performance.now(),ms:performance.now()-e}),this.trimSamples(this.modelRunSamples)}).catch(()=>{}),this.modelTimingCounter++}else this.skippedCount++;let r=performance.now();this.renderOp.runDisplay(),this.displayRunSamples.push({ts:performance.now(),ms:performance.now()-r}),this.trimSamples(this.displayRunSamples),this.framesRenderedAt.push(performance.now()),this.trim(this.framesRenderedAt)}shouldRunModel(){return this.skipCounter===0?(this.skipCounter=this.preset?.skipFrames??0,!0):(this.skipCounter--,!1)}setBackground(t){this.currentBackground=t,this.renderOp.setBackground(this.translateBackground(t))}setEnabled(t){this.enabled=t}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.translateBackground(this.currentBackground)}),this.tierModel=p,this.hPrev=u,this.preset=t,this.skipCounter=0}destroy(){this.bgVideoPort&&(this.bgVideoPort.close(),this.bgVideoPort=null),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}}translateBackground(t){switch(t.kind!=="video"&&this.bgVideoPort&&(this.bgVideoPort.close(),this.bgVideoPort=null),t.kind){case"none":return{mode:"solid",color:[0,0,0]};case"color":return{mode:"solid",color:t.rgb};case"blur":return{mode:"blur",sigma:t.sigma};case"image":return this.bgImageInput||(this.bgImageInput=this.backend.ops.Input(this.canvas.height,this.canvas.width)),this.bgImageInput.setSource(t.bitmap),this.bgImageInput.run(),{mode:"image",image:this.bgImageInput.output};case"video":{this.bgVideoInput||(this.bgVideoInput=this.backend.ops.Input(this.canvas.height,this.canvas.width)),this.bgVideoPort&&this.bgVideoPort.close(),this.bgVideoPort=t.port;let r=this.bgVideoInput;return t.port.onmessage=e=>{let o=e.data.frame;try{r.setSource(o),r.run()}finally{o.close()}},t.port.start?.(),{mode:"image",image:this.bgVideoInput.output}}}}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 I=new Float32Array(1),M=new Uint32Array(I.buffer);function fo(s){I[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 ho(s){let t=(s&32768)<<16,r=(s&31744)>>>10,e=s&1023;if(r===0){if(e===0)return M[0]=t,I[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,I[0]}return r===31?(M[0]=t|2139095040|e<<13,I[0]):(M[0]=t|r+127-15<<23|e<<13,I[0])}function re(s){let t=new Uint16Array(s.length);for(let r=0;r<s.length;r++)t[r]=fo(s[r]);return t}function D(s){let t=new Float32Array(s.length);for(let r=0;r<s.length;r++)t[r]=ho(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 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 fe=false;function ye(a){fe=a;}function v(a){let t=`[longpipe/${a}]`,e=((...r)=>{fe&&console.log(t,...r);});return e.warn=(...r)=>{fe&&console.warn(t,...r);},e}var P=v("adaptive"),Jt=2e3,Qt=1e4,Zt=30,er=20,tr=5e3,rr=.3,nr=15e3,S=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));},Jt);}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<Qt)return;let e=await this.opts.getStats();if(e.fps<er?(this.overshootStart===0&&(this.overshootStart=t),t-this.overshootStart>=tr&&this.tryDowngrade(e.fps)):this.overshootStart=0,this.opts.backendKind==="webgpu"&&e.modelMs>0){let r=1e3/Zt*rr;e.modelMs<r?(this.headroomStart===0&&(this.headroomStart=t),t-this.headroomStart>=nr&&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=await this.opts.fetchWeights(e.model);await this.opts.swapPreset(e.model,r),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 ke(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 x=new VideoFrame(r,{timestamp:h.mediaTime*1e6});i.postMessage({frame:x},[x]);}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 ar=4,he=8,Ce=16;async function G(a){if(typeof a=="string")return a==="none"?{background:{kind:"none"}}:a==="blur"?{background:{kind:"blur",sigma:he}}:{background:{kind:"image",bitmap:await Te(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 Pe(a);let t=a;if(t.color!==void 0)return {background:{kind:"color",rgb:ir(t.color)}};if(t.blur!==void 0)return {background:{kind:"blur",sigma:or(t.blur)}};if(t.image!==void 0)return {background:{kind:"image",bitmap:await sr(t.image)}};if(t.video!==void 0)return await Pe(t.video);throw new Error(`background: unrecognized input shape \u2014 ${k(a)}`)}async function Pe(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 ke(t);return {background:{kind:"video",port:e.port},transferList:e.transferList,cleanup:e.cleanup}}function ir(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 or(a){if(a===true)return he;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 Ce*e}if(t==="low")return ar;if(t==="medium")return he;if(t==="high")return Ce;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 sr(a){if(a instanceof ImageBitmap)return a;if(typeof HTMLImageElement<"u"&&a instanceof HTMLImageElement)return createImageBitmap(a);if(typeof a=="string")return Te(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 Te(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 Ue(){return {input:"MediaStreamTrackProcessor"in self?"mstp":"rvfc-postmessage",output:"MediaStreamTrackGenerator"in self?"mstg":ur()?"transfer-capture":"bitmap-shuttle"}}var F=null;function ur(){return F!==null||(F=!/Firefox/.test(navigator.userAgent)),F}function We(a,t,e){let r=[a];return e==="passthrough"&&r.push(...t.getAudioTracks()),new MediaStream(r)}var E=v("worker_controller"),A=class{worker;listeners=new Map;persistentEvents=new Set;constructor(t){this.worker=t,this.worker.addEventListener("message",this.handleMessage.bind(this)),E("constructed; message listener attached");}handleMessage(t){let{request_id:e,res:r}=t.data,n=this.listeners.get(e);E("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),E("addPersistentListener:",t);}removePersistentListener(t){this.persistentEvents.delete(t),this.listeners.delete(t);}sendMessage(t,e,r=[]){let n=crypto.randomUUID();return E("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 Ie=v("input-postmessage/main");function Be(a){let t=document.createElement("video");t.srcObject=a,t.muted=true,t.autoplay=true,t.playsInline=true,t.play().catch(l=>{Ie.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){Ie.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 Se(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 Ge(a,t){switch(a){case "mstp":{let e=Se(t);return {initFields:{inputReadable:e.readable},transferList:e.transferList,cleanup:e.cleanup}}case "rvfc-postmessage":{let e=Be(t);return {initFields:{inputPort:e.port},transferList:e.transferList,cleanup:e.cleanup}}}}var pr=v("bitmap-shuttle/main"),lr=30;function Fe(a,t=lr){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=()=>{},x=3,we=0;return u.onmessage=W=>{if(c){if(we++,we<x){W.data.bmp.close();return}h();}try{r.transferFromImageBitmap(W.data.bmp);}catch(b){pr.warn("transferFromImageBitmap failed:",b);}},u.start(),{videoTrack:o,port:l,transferList:[l],startPassthrough:W=>{if(c)return;c=true;let b=document.createElement("video");b.srcObject=W,b.muted=true,b.playsInline=true,b.play().catch(()=>{}),f=b;let I="requestVideoFrameCallback"in b?C=>{b.requestVideoFrameCallback(C);}:C=>{requestAnimationFrame(C);},B=()=>{if(c){if(b.videoWidth===0){I(B);return}createImageBitmap(b,{resizeWidth:e.width,resizeHeight:e.height,resizeQuality:"medium"}).then(C=>{if(!c){C.close();return}try{r.transferFromImageBitmap(C);}catch{}I(B);}).catch(()=>{I(B);});}};I(B),h=()=>{c=false,f&&(f.srcObject=null,f.pause(),f=null);};},cleanup:()=>{h(),u.onmessage=null,u.close(),o.stop();}}}function Ee(){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 Ae(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 Oe(a,t){switch(a){case "mstg":{let e=Ee();return {videoTrack:e.videoTrack,initFields:{outputWritable:e.writable},transferList:e.transferList,cleanup:e.cleanup}}case "transfer-capture":{let e=Ae(t);return {videoTrack:e.videoTrack,initFields:{outputCanvas:e.canvas},transferList:e.transferList,cleanup:e.cleanup}}case "bitmap-shuttle":{let e=Fe(t);return {videoTrack:e.videoTrack,initFields:{outputPort:e.port},transferList:e.transferList,startPassthrough:e.startPassthrough,cleanup:e.cleanup}}}}var ge=`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
2
  //
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).
3
+ // Identical math, layout, and output to conv2d.wgsl, but each thread computes 2
4
+ // output channel-groups (8 channels) for one pixel, loading each input vec4 ONCE
5
+ // and reusing it across both groups' mat4x4 weight blocks in registers. Half the
6
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
7
+ // identical to conv2d.wgsl (\\u22641 ULP from FMA contraction). Dispatch
8
+ // ceil(out_groups / 2) in z (see conv2d.ts).
10
9
  //
11
10
  // Tensor layout: NHWC, channels in vec4 groups (same as conv2d.wgsl).
12
11
  // Weight layout: [K*K][out_groups][in_groups] array of mat4x4 (same as conv2d.wgsl).
@@ -23,7 +22,7 @@ struct Params {
23
22
  stride : u32,
24
23
  pad_top : u32,
25
24
  pad_left : u32,
26
- activation : u32, // 0 = none, 1 = relu6, 2 = relu
25
+ activation : u32, // 0 = none, 1 = relu6, 2 = relu, 3 = leaky
27
26
  }
28
27
 
29
28
  @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
@@ -32,18 +31,19 @@ struct Params {
32
31
  @group(0) @binding(3) var<uniform> params : Params;
33
32
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
34
33
 
35
- const KB = 4u;
34
+ const KB = 2u;
36
35
 
37
36
  fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
38
37
  if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
39
38
  if (a == 2u) { return max(v, vec4<f32>(0.0)); }
39
+ if (a == 3u) { return max(v, 0.1 * v); } // leaky relu (slope 0.1)
40
40
  return v;
41
41
  }
42
42
 
43
43
  @compute @workgroup_size(8, 8, 1)
44
44
  fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
45
- let x = gid.x; // output column
46
- let y = gid.y; // output row
45
+ let x = gid.x; // output column
46
+ let y = gid.y; // output row
47
47
  let o0 = gid.z * KB; // first output channel group
48
48
 
49
49
  if (x >= params.out_w || y >= params.out_h || o0 >= params.out_groups) {
@@ -52,19 +52,13 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
52
52
 
53
53
  let I = params.in_groups;
54
54
  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.
55
+ // Tail handling when out_groups is odd: clamp the spare lane to o0 (valid
56
+ // index, no OOB) and just don't write it.
57
57
  let has1 = (o0 + 1u) < O;
58
- let has2 = (o0 + 2u) < O;
59
- let has3 = (o0 + 3u) < O;
60
58
  let o1 = select(o0, o0 + 1u, has1);
61
- let o2 = select(o0, o0 + 2u, has2);
62
- let o3 = select(o0, o0 + 3u, has3);
63
59
 
64
60
  var acc0 = bias_buf[o0];
65
61
  var acc1 = bias_buf[o1];
66
- var acc2 = bias_buf[o2];
67
- var acc3 = bias_buf[o3];
68
62
 
69
63
  for (var ky = 0u; ky < params.kernel_h; ky++) {
70
64
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -80,14 +74,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
80
74
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
81
75
  let wb0 = z * O * I + o0 * I;
82
76
  let wb1 = z * O * I + o1 * I;
83
- let wb2 = z * O * I + o2 * I;
84
- let wb3 = z * O * I + o3 * I;
85
77
  for (var i = 0u; i < I; i++) {
86
- let iv = input_buf[inB + i]; // loaded ONCE, reused across 4 groups
78
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
87
79
  acc0 += weight_buf[wb0 + i] * iv;
88
80
  acc1 += weight_buf[wb1 + i] * iv;
89
- acc2 += weight_buf[wb2 + i] * iv;
90
- acc3 += weight_buf[wb3 + i] * iv;
91
81
  }
92
82
  }
93
83
  }
@@ -95,15 +85,14 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
95
85
  let baseO = y * params.out_w * O + x * O;
96
86
  output_buf[baseO + o0] = act(acc0, params.activation);
97
87
  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
88
  }
101
- \`;var xt=\`enable f16;
89
+ \`;var Et=\`enable f16;
102
90
 
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.
91
+ // Conv2d, output-channel-blocked (K=2) \\u2014 full f16. Drop-in replacement for
92
+ // conv2d_f16.wgsl. Each thread computes 2 output channel-groups for one pixel,
93
+ // loading each input vec4 ONCE and reusing it across both weight blocks. Half the
94
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
95
+ // identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 2) in z.
107
96
 
108
97
  struct Params {
109
98
  in_h : u32,
@@ -126,11 +115,12 @@ struct Params {
126
115
  @group(0) @binding(3) var<uniform> params : Params;
127
116
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
128
117
 
129
- const KB = 4u;
118
+ const KB = 2u;
130
119
 
131
120
  fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
132
121
  if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
133
122
  if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
123
+ if (a == 3u) { return max(v, 0.1h * v); } // leaky relu (slope 0.1)
134
124
  return v;
135
125
  }
136
126
 
@@ -147,16 +137,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
147
137
  let I = params.in_groups;
148
138
  let O = params.out_groups;
149
139
  let has1 = (o0 + 1u) < O;
150
- let has2 = (o0 + 2u) < O;
151
- let has3 = (o0 + 3u) < O;
152
140
  let o1 = select(o0, o0 + 1u, has1);
153
- let o2 = select(o0, o0 + 2u, has2);
154
- let o3 = select(o0, o0 + 3u, has3);
155
141
 
156
142
  var acc0 = bias_buf[o0];
157
143
  var acc1 = bias_buf[o1];
158
- var acc2 = bias_buf[o2];
159
- var acc3 = bias_buf[o3];
160
144
 
161
145
  for (var ky = 0u; ky < params.kernel_h; ky++) {
162
146
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -172,14 +156,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
172
156
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
173
157
  let wb0 = z * O * I + o0 * I;
174
158
  let wb1 = z * O * I + o1 * I;
175
- let wb2 = z * O * I + o2 * I;
176
- let wb3 = z * O * I + o3 * I;
177
159
  for (var i = 0u; i < I; i++) {
178
- let iv = input_buf[inB + i];
160
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
179
161
  acc0 += weight_buf[wb0 + i] * iv;
180
162
  acc1 += weight_buf[wb1 + i] * iv;
181
- acc2 += weight_buf[wb2 + i] * iv;
182
- acc3 += weight_buf[wb3 + i] * iv;
183
163
  }
184
164
  }
185
165
  }
@@ -187,10 +167,156 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
187
167
  let baseO = y * params.out_w * O + x * O;
188
168
  output_buf[baseO + o0] = act(acc0, params.activation);
189
169
  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
170
  }
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 bo(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"?bo(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"?xt: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 vt=\`// Depthwise Conv2d \\u2014 groups = in_channels (each channel convolved independently).
171
+ \`;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
172
+ // the math; this is the f32 storage build (mat4x4<f32>).
173
+
174
+ struct Params {
175
+ in_h : u32,
176
+ in_w : u32,
177
+ out_h : u32,
178
+ out_w : u32,
179
+ in_groups : u32,
180
+ out_groups : u32,
181
+ kernel_h : u32,
182
+ kernel_w : u32,
183
+ stride : u32,
184
+ pad_top : u32,
185
+ pad_left : u32,
186
+ activation : u32,
187
+ }
188
+
189
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
190
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f32>>;
191
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f32>>;
192
+ @group(0) @binding(3) var<uniform> params : Params;
193
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
194
+
195
+ fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
196
+ if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
197
+ if (a == 2u) { return max(v, vec4<f32>(0.0)); }
198
+ if (a == 3u) { return max(v, 0.1 * v); }
199
+ return v;
200
+ }
201
+
202
+ @compute @workgroup_size(8, 8, 1)
203
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
204
+ let ox = gid.x;
205
+ let oy = gid.y;
206
+ let o = gid.z;
207
+
208
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
209
+ return;
210
+ }
211
+
212
+ let I = params.in_groups;
213
+ let O = params.out_groups;
214
+ let s = i32(params.stride);
215
+
216
+ var result = bias_buf[o];
217
+
218
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
219
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
220
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
221
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
222
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
223
+ continue;
224
+ }
225
+ let iy = iy_num / s;
226
+ let ix = ix_num / s;
227
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
228
+ continue;
229
+ }
230
+
231
+ let z = ky * params.kernel_w + kx;
232
+ for (var i = 0u; i < I; i++) {
233
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
234
+ let w_idx = z * O * I + o * I + i;
235
+ result += weight_buf[w_idx] * input_buf[in_idx];
236
+ }
237
+ }
238
+ }
239
+
240
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
241
+ }
242
+ \`;var Ot=\`enable f16;
243
+
244
+ // ConvTranspose2d \\u2014 gather form, full f16 variant.
245
+ // Each output (oy,ox) sums every input pixel + kernel tap that maps onto it:
246
+ // iy = (oy + pad - ky) / stride (must divide evenly and be in bounds)
247
+ // No explicit kernel flip \\u2014 the (oy + pad - ky) indexing carries it.
248
+ // Weight layout is IDENTICAL to conv2d (mat4x4[z][o][i], M[in_sub][out_sub] =
249
+ // W(in, out, ky, kx)), so the op uploads the flat buffer unchanged.
250
+
251
+ struct Params {
252
+ in_h : u32,
253
+ in_w : u32,
254
+ out_h : u32,
255
+ out_w : u32,
256
+ in_groups : u32,
257
+ out_groups : u32,
258
+ kernel_h : u32,
259
+ kernel_w : u32,
260
+ stride : u32,
261
+ pad_top : u32,
262
+ pad_left : u32,
263
+ activation : u32,
264
+ }
265
+
266
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
267
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f16>>;
268
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f16>>;
269
+ @group(0) @binding(3) var<uniform> params : Params;
270
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
271
+
272
+ fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
273
+ if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
274
+ if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
275
+ if (a == 3u) { return max(v, 0.1h * v); }
276
+ return v;
277
+ }
278
+
279
+ @compute @workgroup_size(8, 8, 1)
280
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
281
+ let ox = gid.x;
282
+ let oy = gid.y;
283
+ let o = gid.z;
284
+
285
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
286
+ return;
287
+ }
288
+
289
+ let I = params.in_groups;
290
+ let O = params.out_groups;
291
+ let s = i32(params.stride);
292
+
293
+ var result = bias_buf[o];
294
+
295
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
296
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
297
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
298
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
299
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
300
+ continue;
301
+ }
302
+ let iy = iy_num / s;
303
+ let ix = ix_num / s;
304
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
305
+ continue;
306
+ }
307
+
308
+ let z = ky * params.kernel_w + kx;
309
+ for (var i = 0u; i < I; i++) {
310
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
311
+ let w_idx = z * O * I + o * I + i;
312
+ result += weight_buf[w_idx] * input_buf[in_idx];
313
+ }
314
+ }
315
+ }
316
+
317
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
318
+ }
319
+ \`;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
320
  //
195
321
  // Weight layout: [K*K][channel_groups] array of vec4
196
322
  // weight index = (ky*kernel_w + kx) * channel_groups + c
@@ -265,7 +391,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
265
391
  let out_idx = y * params.out_w * C + x * C + c;
266
392
  output_buf[out_idx] = result;
267
393
  }
268
- \`;var yt=\`enable f16;
394
+ \`;var At=\`enable f16;
269
395
 
270
396
  // Depthwise conv2d \\u2014 full f16 variant. All buffers f16.
271
397
 
@@ -330,7 +456,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
330
456
 
331
457
  output_buf[y * params.out_w * C + x * C + c] = result;
332
458
  }
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:vt;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.
459
+ \`;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
460
  // Operates on the flat float buffer directly; layout is irrelevant for a pure element-wise op.
335
461
 
336
462
  struct Params {
@@ -351,7 +477,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
351
477
  if (idx >= params.size) { return; }
352
478
  output[idx] = input_a[idx] + input_b[idx];
353
479
  }
354
- \`;var kt=\`enable f16;
480
+ \`;var Rt=\`enable f16;
355
481
 
356
482
  // Element-wise add \\u2014 full f16 variant.
357
483
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -374,7 +500,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
374
500
  if (idx >= params.size) { return; }
375
501
  output[idx] = input_a[idx] + input_b[idx];
376
502
  }
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)).
503
+ \`;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
504
  // Operates on packed vec4 buffers (NHWC layout). exp() and arithmetic are element-wise on vec4.
379
505
 
380
506
  struct Params {
@@ -394,7 +520,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
394
520
  if (idx >= params.n_groups) { return; }
395
521
  output_buf[idx] = 1.0 / (1.0 + exp(-input_buf[idx]));
396
522
  }
397
- \`;var Ct=\`enable f16;
523
+ \`;var zt=\`enable f16;
398
524
 
399
525
  // Sigmoid \\u2014 full f16 variant.
400
526
 
@@ -416,7 +542,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
416
542
  let x = vec4<f32>(input_buf[idx]);
417
543
  output_buf[idx] = vec4<f16>(1.0 / (1.0 + exp(-x)));
418
544
  }
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.
545
+ \`;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
546
  // Operates on packed vec4 buffers (NHWC layout). tanh() is element-wise on vec4.
421
547
 
422
548
  struct Params {
@@ -436,7 +562,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
436
562
  if (idx >= params.n_groups) { return; }
437
563
  output_buf[idx] = tanh(input_buf[idx]);
438
564
  }
439
- \`;var Pt=\`enable f16;
565
+ \`;var Nt=\`enable f16;
440
566
 
441
567
  // Tanh \\u2014 full f16 variant.
442
568
 
@@ -458,7 +584,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
458
584
  let x = vec4<f32>(input_buf[idx]);
459
585
  output_buf[idx] = vec4<f16>(tanh(x));
460
586
  }
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.
587
+ \`;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
588
  // Same flat-float layout as add.wgsl.
463
589
 
464
590
  struct Params {
@@ -479,7 +605,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
479
605
  if (idx >= params.size) { return; }
480
606
  output[idx] = input_a[idx] * input_b[idx];
481
607
  }
482
- \`;var Bt=\`enable f16;
608
+ \`;var Xt=\`enable f16;
483
609
 
484
610
  // Element-wise multiply \\u2014 full f16 variant.
485
611
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -502,7 +628,208 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
502
628
  if (idx >= params.size) { return; }
503
629
  output[idx] = input_a[idx] * input_b[idx];
504
630
  }
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).
631
+ \`;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.
632
+
633
+ struct Params {
634
+ h : u32,
635
+ w : u32,
636
+ flow_scale : f32,
637
+ }
638
+
639
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f32>>;
640
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f32>>;
641
+ @group(0) @binding(2) var<uniform> params : Params;
642
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f32>>;
643
+
644
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
645
+ let cx = clamp(x, 0, W - 1);
646
+ let cy = clamp(y, 0, H - 1);
647
+ return source_buf[u32(cy) * u32(W) + u32(cx)];
648
+ }
649
+
650
+ @compute @workgroup_size(8, 8, 1)
651
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
652
+ let x = gid.x;
653
+ let y = gid.y;
654
+ if (x >= params.w || y >= params.h) { return; }
655
+
656
+ let W = i32(params.w);
657
+ let H = i32(params.h);
658
+ let idx = y * params.w + x;
659
+
660
+ let f = flow_buf[idx].xy;
661
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
662
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
663
+
664
+ let x0 = i32(floor(sx));
665
+ let y0 = i32(floor(sy));
666
+ let tx = sx - f32(x0);
667
+ let ty = sy - f32(y0);
668
+
669
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
670
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
671
+ output_buf[idx] = mix(top, bot, ty);
672
+ }
673
+ \`;var qt=\`enable f16;
674
+
675
+ // Bilinear gather-warp (f16 storage, f32 coordinate math). For each output pixel
676
+ // p, sample the source at p + flow_scale\\xB7flow[p].xy and bilinearly interpolate,
677
+ // clamping the sample to the edge (border-replicate). Source + flow are 4-ch
678
+ // (1 group), same resolution; flow vector is in .xy.
679
+
680
+ struct Params {
681
+ h : u32,
682
+ w : u32,
683
+ flow_scale : f32,
684
+ }
685
+
686
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f16>>;
687
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f16>>;
688
+ @group(0) @binding(2) var<uniform> params : Params;
689
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f16>>;
690
+
691
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
692
+ let cx = clamp(x, 0, W - 1);
693
+ let cy = clamp(y, 0, H - 1);
694
+ return vec4<f32>(source_buf[u32(cy) * u32(W) + u32(cx)]);
695
+ }
696
+
697
+ @compute @workgroup_size(8, 8, 1)
698
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
699
+ let x = gid.x;
700
+ let y = gid.y;
701
+ if (x >= params.w || y >= params.h) { return; }
702
+
703
+ let W = i32(params.w);
704
+ let H = i32(params.h);
705
+ let idx = y * params.w + x;
706
+
707
+ let f = vec2<f32>(flow_buf[idx].xy);
708
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
709
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
710
+
711
+ let x0 = i32(floor(sx));
712
+ let y0 = i32(floor(sy));
713
+ let tx = sx - f32(x0);
714
+ let ty = sy - f32(y0);
715
+
716
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
717
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
718
+ output_buf[idx] = vec4<f16>(mix(top, bot, ty));
719
+ }
720
+ \`;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.
721
+
722
+ struct Params {
723
+ h : u32,
724
+ w : u32,
725
+ t_lo : f32,
726
+ t_hi : f32,
727
+ leak : f32,
728
+ release : f32,
729
+ t_div : f32,
730
+ div_scale: f32,
731
+ step_x : u32,
732
+ step_y : u32,
733
+ }
734
+
735
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f32>>;
736
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f32>>;
737
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f32>>;
738
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f32>>;
739
+ @group(0) @binding(4) var<uniform> params : Params;
740
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f32>>;
741
+
742
+ @compute @workgroup_size(8, 8, 1)
743
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
744
+ let x = gid.x;
745
+ let y = gid.y;
746
+ if (x >= params.w || y >= params.h) { return; }
747
+ let idx = y * params.w + x;
748
+
749
+ let mag = length(flow_buf[idx].xy);
750
+ let env_prev = env_prev_buf[idx].y;
751
+ let env = max(mag, params.release * env_prev);
752
+
753
+ let xr = min(x + params.step_x, params.w - 1u);
754
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
755
+ let yd = min(y + params.step_y, params.h - 1u);
756
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
757
+ let dfx = flow_buf[y * params.w + xr].x - flow_buf[y * params.w + xl].x;
758
+ let dfy = flow_buf[yd * params.w + x].y - flow_buf[yu * params.w + x].y;
759
+ let divg = abs(dfx + dfy);
760
+
761
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
762
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
763
+ let g = max(max(g_mag, g_div), params.leak);
764
+
765
+ let pred = pred_buf[idx].x;
766
+ let refv = ref_buf[idx].x;
767
+ let stab = g * pred + (1.0 - g) * refv;
768
+
769
+ output_buf[idx] = vec4<f32>(stab, env, 0.0, 0.0);
770
+ }
771
+ \`;var Yt=\`enable f16;
772
+
773
+ // Flow-gated temporal stabilizer (f16 storage, f32 gate math). Per pixel:
774
+ // env = max(|flow.xy|, release\\xB7envPrev.y) peak-hold (fast attack, slow release)
775
+ // div = |\\u2202fx/\\u2202x + \\u2202fy/\\u2202y| flow divergence (occlusion seam)
776
+ // g = max(clamp((env-tLo)/(tHi-tLo),0,1), clamp((div-tDiv)/divScale,0,1), leak)
777
+ // out = vec4((g\\xB7pred + (1-g)\\xB7ref).x, env, 0, 0)
778
+ // The divergence term opens the gate at occlusion/disocclusion boundaries (where
779
+ // the flow tears but the revealed-background magnitude is ~0). Finite-difference
780
+ // step spans ~1 base/4 pixel. alpha is in .x of pred/ref; env threads via .y.
781
+
782
+ struct Params {
783
+ h : u32,
784
+ w : u32,
785
+ t_lo : f32,
786
+ t_hi : f32,
787
+ leak : f32,
788
+ release : f32,
789
+ t_div : f32,
790
+ div_scale: f32,
791
+ step_x : u32,
792
+ step_y : u32,
793
+ }
794
+
795
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f16>>;
796
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f16>>;
797
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f16>>;
798
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f16>>;
799
+ @group(0) @binding(4) var<uniform> params : Params;
800
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f16>>;
801
+
802
+ @compute @workgroup_size(8, 8, 1)
803
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
804
+ let x = gid.x;
805
+ let y = gid.y;
806
+ if (x >= params.w || y >= params.h) { return; }
807
+ let idx = y * params.w + x;
808
+
809
+ let mag = length(vec2<f32>(flow_buf[idx].xy));
810
+ let env_prev = f32(env_prev_buf[idx].y);
811
+ let env = max(mag, params.release * env_prev);
812
+
813
+ // Flow divergence over a \\xB1step finite-difference (clamped to the edges).
814
+ let xr = min(x + params.step_x, params.w - 1u);
815
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
816
+ let yd = min(y + params.step_y, params.h - 1u);
817
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
818
+ let dfx = f32(flow_buf[y * params.w + xr].x) - f32(flow_buf[y * params.w + xl].x);
819
+ let dfy = f32(flow_buf[yd * params.w + x].y) - f32(flow_buf[yu * params.w + x].y);
820
+ let divg = abs(dfx + dfy);
821
+
822
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
823
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
824
+ let g = max(max(g_mag, g_div), params.leak);
825
+
826
+ let pred = f32(pred_buf[idx].x);
827
+ let refv = f32(ref_buf[idx].x);
828
+ let stab = g * pred + (1.0 - g) * refv;
829
+
830
+ output_buf[idx] = vec4<f16>(f16(stab), f16(env), 0.0h, 0.0h);
831
+ }
832
+ \`;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
833
  // Input/output in NHWC vec4 format: index = y*W*(C/4) + x*(C/4) + c_group.
507
834
  // Each thread computes one output pixel for one channel group (vec4 = 4 channels).
508
835
 
@@ -560,7 +887,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
560
887
 
561
888
  output_buf[oy * params.out_w * C + ox * C + c] = result;
562
889
  }
563
- \`;var St=\`enable f16;
890
+ \`;var Jt=\`enable f16;
564
891
 
565
892
  // Bilinear upsample 2\\xD7 \\u2014 full f16 variant.
566
893
  // Interpolation weights (wx, wy) and intermediate blends computed in f32 for
@@ -616,7 +943,53 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
616
943
 
617
944
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(result);
618
945
  }
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
946
+ \`;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.
947
+
948
+ struct Params {
949
+ in_w : u32,
950
+ out_h : u32,
951
+ out_w : u32,
952
+ groups : u32,
953
+ }
954
+
955
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
956
+ @group(0) @binding(1) var<uniform> params : Params;
957
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f32>>;
958
+
959
+ @compute @workgroup_size(8, 8, 1)
960
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
961
+ let x = gid.x;
962
+ let y = gid.y;
963
+ let g = gid.z;
964
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
965
+ let G = params.groups;
966
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
967
+ }
968
+ \`;var er=\`enable f16;
969
+
970
+ // Top-left crop: output[y,x,g] = input[y,x,g] for y<outH, x<outW (training crop_like).
971
+
972
+ struct Params {
973
+ in_w : u32,
974
+ out_h : u32,
975
+ out_w : u32,
976
+ groups : u32,
977
+ }
978
+
979
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
980
+ @group(0) @binding(1) var<uniform> params : Params;
981
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f16>>;
982
+
983
+ @compute @workgroup_size(8, 8, 1)
984
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
985
+ let x = gid.x;
986
+ let y = gid.y;
987
+ let g = gid.z;
988
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
989
+ let G = params.groups;
990
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
991
+ }
992
+ \`;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
993
  // for mode='bicubic', align_corners=False). Direct 2D, 4\\xD74 = 16 taps per
621
994
  // output pixel. NHWC vec4 layout: index = y*W*(C/4) + x*(C/4) + c_group.
622
995
 
@@ -683,7 +1056,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
683
1056
 
684
1057
  output_buf[oy * params.out_w * C + ox * C + c] = acc;
685
1058
  }
686
- \`;var Ft=\`enable f16;
1059
+ \`;var rr=\`enable f16;
687
1060
 
688
1061
  // Bicubic upsample \\u2014 full f16 storage variant. Bicubic weights and the per-
689
1062
  // pixel accumulator are computed in f32 (cheap to keep precision around the
@@ -752,7 +1125,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
752
1125
 
753
1126
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(acc);
754
1127
  }
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).
1128
+ \`;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
1129
  // Both A and B must share the same H\\xD7W and be in NHWC vec4 format.
757
1130
  // Output layout: for each (y, x), the first a_groups vec4s come from A,
758
1131
  // followed by b_groups vec4s from B.
@@ -797,7 +1170,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
797
1170
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
798
1171
  }
799
1172
  }
800
- \`;var It=\`enable f16;
1173
+ \`;var ir=\`enable f16;
801
1174
 
802
1175
  // Channel concatenation \\u2014 full f16 variant.
803
1176
 
@@ -838,7 +1211,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
838
1211
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
839
1212
  }
840
1213
  }
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"?It: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 Dt=\`// Conv2d + skip add fused.
1214
+ \`;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
1215
  // Identical to conv2d.wgsl except skip is an activation input (binding 1),
843
1216
  // added element-wise to the conv result at write time.
844
1217
  // Eliminates the separate add dispatch and its intermediate buffer round-trip.
@@ -912,7 +1285,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
912
1285
  let out_idx = y * params.out_w * O + x * O + o;
913
1286
  output_buf[out_idx] = result + skip_buf[out_idx];
914
1287
  }
915
- \`;var Ot=\`enable f16;
1288
+ \`;var nr=\`enable f16;
916
1289
 
917
1290
  // Conv2d + skip add fused \\u2014 full f16 variant.
918
1291
 
@@ -986,7 +1359,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
986
1359
  let out_idx = y * params.out_w * O + x * O + o;
987
1360
  output_buf[out_idx] = result + skip_buf[out_idx];
988
1361
  }
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"?Ot:Dt;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.
1362
+ \`;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
1363
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation: drops
991
1364
  // the kernel loop, the padding checks, and the activation branch. Used by the
992
1365
  // MBConv project+residual tail. Both inputs share the same spatial resolution.
@@ -1031,7 +1404,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1031
1404
 
1032
1405
  output_buf[pix * O + o] = result;
1033
1406
  }
1034
- \`;var Rt=\`enable f16;
1407
+ \`;var ur=\`enable f16;
1035
1408
 
1036
1409
  // proj_residual \\u2014 full f16 variant. See proj_residual.wgsl for layout details.
1037
1410
  // Bespoke 1\\xD71 conv (no activation) + residual add, fused.
@@ -1073,7 +1446,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1073
1446
 
1074
1447
  output_buf[pix * O + o] = result;
1075
1448
  }
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
1449
+ \`;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
1450
  // dispatch. Both inputs are already at the output resolution (the upstream
1078
1451
  // upsample stays a separate dispatch writing a clean intermediate, so the conv
1079
1452
  // reads are plain-indexed). Identical math to conv2d; the only difference is
@@ -1133,7 +1506,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1133
1506
  result = clamp(result, vec4<f32>(0.0), vec4<f32>(6.0));
1134
1507
  output_buf[(y * p.w + x) * O + o] = result;
1135
1508
  }
1136
- \`;var Ht=\`enable f16;
1509
+ \`;var lr=\`enable f16;
1137
1510
 
1138
1511
  // concat_conv2d \\u2014 full f16 variant. See concat_conv2d.wgsl for layout details.
1139
1512
  // Fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one dispatch.
@@ -1188,7 +1561,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1188
1561
  result = clamp(result, vec4<f16>(0.0h), vec4<f16>(6.0h));
1189
1562
  output_buf[(y * p.w + x) * O + o] = result;
1190
1563
  }
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.
1564
+ \`;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
1565
  // Production config (c_up=2, split_ratio=0.5 \\u2192 passthrough=1, recurrent=1):
1193
1566
  // u_in : c_up=2 packed in a vec4 (.x = passthrough a, .y = recurrent b)
1194
1567
  // h_prev : hidden carrier \\u2014 recurrent state in .z (see cand_update_fused: the
@@ -1233,7 +1606,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1233
1606
  let r = 1.0 / (1.0 + exp(-r_pre));
1234
1607
  output_buf[y * params.w + x] = vec4<f32>(z, r, 0.0, 0.0);
1235
1608
  }
1236
- \`;var Vt=\`enable f16;
1609
+ \`;var dr=\`enable f16;
1237
1610
 
1238
1611
  // gates_fused \\u2014 full f16 variant. See gates_fused.wgsl for layout details.
1239
1612
  // ConvGRU z + r gates (production config c_up=2, recurrent=1).
@@ -1275,7 +1648,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1275
1648
  let r = 1.0h / (1.0h + exp(-r_pre));
1276
1649
  output_buf[y * params.w + x] = vec4<f16>(z, r, 0.0h, 0.0h);
1277
1650
  }
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.
1651
+ \`;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
1652
  // Production config (c_up=2, recurrent=1):
1280
1653
  // u_in : c_up=2 (.x = a passthrough, .y = b recurrent)
1281
1654
  // h_prev : hidden carrier \\u2014 recurrent state in .z (the previous frame's
@@ -1328,7 +1701,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1328
1701
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
1329
1702
  output_buf[cur] = vec4<f32>(u_cur.x, b_out, h_new, 0.0);
1330
1703
  }
1331
- \`;var $t=\`enable f16;
1704
+ \`;var fr=\`enable f16;
1332
1705
 
1333
1706
  // cand_update_fused \\u2014 full f16 variant. See cand_update_fused.wgsl for details.
1334
1707
  // ConvGRU candidate + state update + output (production config c_up=2, recurrent=1).
@@ -1374,7 +1747,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1374
1747
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
1375
1748
  output_buf[cur] = vec4<f16>(u_cur.x, b_out, h_new, 0.0h);
1376
1749
  }
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).
1750
+ \`;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
1751
  // Expands feat_lr (in_c, mult of 4) to the c_up=2 carrier \\u2014 output .xy = the 2
1379
1752
  // native channels, .zw = 0. mat4x2 per (kpos, in_group) with a vec2 accumulator.
1380
1753
  // Weight: 9 * in_groups mat4x2 (8 floats each, col-major). Bias .xy.
@@ -1411,7 +1784,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1411
1784
  result = max(result, vec2<f32>(0.0)); // expand_feat is F.relu
1412
1785
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
1413
1786
  }
1414
- \`;var jt=\`enable f16;
1787
+ \`;var _r=\`enable f16;
1415
1788
 
1416
1789
  // conv_expand \\u2014 full f16 variant. See conv_expand.wgsl for layout details.
1417
1790
  // Bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
@@ -1448,7 +1821,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1448
1821
  result = max(result, vec2<f16>(0.0h));
1449
1822
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
1450
1823
  }
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).
1824
+ \`;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
1825
  // u = c_up=2 carrier (.xy); d = c_high=4 (full vec4). Both same resolution.
1453
1826
  // Channel order concat([u, d]) = (u.x, u.y, d.x, d.y, d.z, d.w), split into
1454
1827
  // v3a = (u.x, u.y, d.x) v3b = d.yzw
@@ -1488,7 +1861,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1488
1861
  result = max(result, vec2<f32>(0.0)); // up1_combine is F.relu
1489
1862
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
1490
1863
  }
1491
- \`;var Kt=\`enable f16;
1864
+ \`;var br=\`enable f16;
1492
1865
 
1493
1866
  // cat_conv_6to2 \\u2014 full f16 variant. See cat_conv_6to2.wgsl for layout details.
1494
1867
  // Fused concat(u, d) + 6\\u21922 conv 3\\xD73 (pad 1) + relu (E up1_combine).
@@ -1527,7 +1900,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1527
1900
  result = max(result, vec2<f16>(0.0h));
1528
1901
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
1529
1902
  }
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
1903
+ \`;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
1904
  // act) into one dispatch. E variant: down2 (c_high=4 \\u2192 c_low=4, stride 2) +
1532
1905
  // adapter. A/B variant: down1 (RGB .xyz \\u2192 4, stride 2/3) + adapter (the down
1533
1906
  // weight's 4th input column is zeroed at export for RGB input). Symmetric pad.
@@ -1575,7 +1948,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1575
1948
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
1576
1949
  output_buf[y * p.out_w + x] = vec4<f32>(adapt_out.xyz, 0.0);
1577
1950
  }
1578
- \`;var Qt=\`enable f16;
1951
+ \`;var xr=\`enable f16;
1579
1952
 
1580
1953
  // down_adapter \\u2014 full f16 variant. See down_adapter.wgsl for layout details.
1581
1954
  // Fused stride-N 3\\xD73 conv (4\\u21924) + relu + 1\\xD71 adapter (4\\u21923, no act).
@@ -1620,7 +1993,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1620
1993
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
1621
1994
  output_buf[y * p.out_w + x] = vec4<f16>(adapt_out.xyz, 0.0h);
1622
1995
  }
1623
- \`;var xe=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).
1996
+ \`;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
1997
  // u = c_up=2 carrier (.xy); rgb = x_hr (.xyz). 5 inputs \\u2192 1 alpha (output .x).
1625
1998
  // Weight: 18 vec4 \\u2014 [0..8] = (w0, w1, 0, 0) for u per kpos; [9..17] =
1626
1999
  // (w2, w3, w4, 0) for rgb per kpos. Bias .x.
@@ -1654,7 +2027,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1654
2027
 
1655
2028
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
1656
2029
  }
1657
- \`;var Zt=\`enable f16;
2030
+ \`;var wr=\`enable f16;
1658
2031
 
1659
2032
  // up_final \\u2014 full f16 variant. See up_final.wgsl for layout details.
1660
2033
  // Fused concat(u, rgb) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
@@ -1688,7 +2061,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1688
2061
 
1689
2062
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
1690
2063
  }
1691
- \`;var ve=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
2064
+ \`;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
2065
  // \\u2192 sigmoid. u = c_up=2 (.xy); d_full = c_high=4 full-res skip (full vec4);
1693
2066
  // rgb = x_hr (.xyz). Channel order concat = 2 + 4 + 3 = 9. Output .x = alpha.
1694
2067
  // Weight: 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u; [kpos*3+1]=(w2..w5)
@@ -1725,7 +2098,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1725
2098
 
1726
2099
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
1727
2100
  }
1728
- \`;var tr=\`enable f16;
2101
+ \`;var Tr=\`enable f16;
1729
2102
 
1730
2103
  // up_final_skip \\u2014 full f16 variant. See up_final_skip.wgsl for layout details.
1731
2104
  // C/D alpha head: fused concat(u, d_full, rgb) \\u2192 conv 3\\xD73 9\\u21921 \\u2192 sigmoid.
@@ -1761,7 +2134,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1761
2134
 
1762
2135
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
1763
2136
  }
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.
2137
+ \`;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
2138
  // input_a is the decoder tensor at small spatial resolution (in_h \\xD7 in_w).
1766
2139
  // input_b is the encoder skip feature already at output resolution (out_h \\xD7 out_w).
1767
2140
  // For output channels 0..a_groups-1: bilinearly interpolate from input_a.
@@ -1822,7 +2195,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1822
2195
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
1823
2196
  }
1824
2197
  }
1825
- \`;var or=\`enable f16;
2198
+ \`;var Wr=\`enable f16;
1826
2199
 
1827
2200
  // Bilinear upsample + channel concat fused \\u2014 full f16 variant.
1828
2201
  // Bilinear weights (wx, wy) and intermediate blends computed in f32; result cast to f16.
@@ -1882,7 +2255,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1882
2255
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
1883
2256
  }
1884
2257
  }
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.
2258
+ \`;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
2259
  // For each output pixel, bilinearly samples the small input for each in_group,
1887
2260
  // immediately applies the 1\\xD71 conv weights, and writes the activated result.
1888
2261
  // Eliminates the intermediate full-resolution upsample buffer.
@@ -1949,7 +2322,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
1949
2322
 
1950
2323
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
1951
2324
  }
1952
- \`;var ar=\`enable f16;
2325
+ \`;var Gr=\`enable f16;
1953
2326
 
1954
2327
  // Bilinear upsample + 1\\xD71 pointwise conv fused \\u2014 full f16 variant.
1955
2328
  // Bilinear weights and intermediate blends computed in f32; conv accumulation in f16.
@@ -2016,7 +2389,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2016
2389
 
2017
2390
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
2018
2391
  }
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.
2392
+ \`;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
2393
  // Identical to bilinear_upsample.wgsl except sigmoid is applied at write time.
2021
2394
  // Eliminates the intermediate full-resolution buffer and the separate sigmoid dispatch.
2022
2395
 
@@ -2070,7 +2443,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2070
2443
 
2071
2444
  output_buf[oy * params.out_w * C + ox * C + c] = 1.0 / (1.0 + exp(-result));
2072
2445
  }
2073
- \`;var sr=\`enable f16;
2446
+ \`;var Ur=\`enable f16;
2074
2447
 
2075
2448
  // Bilinear upsample + sigmoid fused \\u2014 full f16 variant.
2076
2449
  // Interpolation computed in f32 for accuracy; sigmoid and result cast to f16.
@@ -2125,7 +2498,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2125
2498
 
2126
2499
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(1.0 / (1.0 + exp(-result)));
2127
2500
  }
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.
2501
+ \`;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
2502
  // Fragment writes the canvas's swapchain texture (premultiplied output).
2130
2503
  //
2131
2504
  // Caller invariants (matched in CompositeSolidWebGPU):
@@ -2170,7 +2543,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2170
2543
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
2171
2544
  return vec4<f32>(rgb, 1.0);
2172
2545
  }
2173
- \`;var pr=\`enable f16;
2546
+ \`;var Lr=\`enable f16;
2174
2547
 
2175
2548
  // Composite an RGBA image over a solid background, gated by a 1-ch alpha.
2176
2549
  // f16 variant: image and alpha are stored as f16; values promote to f32 on
@@ -2219,7 +2592,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2219
2592
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
2220
2593
  return vec4<f32>(rgb, 1.0);
2221
2594
  }
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
2595
+ \`;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
2596
  // background image, or a blurred copy of the input).
2224
2597
 
2225
2598
  struct VertexOut {
@@ -2261,7 +2634,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2261
2634
  let rgb = fg * a + bgc * (1.0 - a);
2262
2635
  return vec4<f32>(rgb, 1.0);
2263
2636
  }
2264
- \`;var cr=\`enable f16;
2637
+ \`;var Er=\`enable f16;
2265
2638
 
2266
2639
  // Like composite_solid_f16 but bg is an NHWC vec4<f16> storage buffer (e.g. a
2267
2640
  // virtual background image, or a blurred copy of the input).
@@ -2305,7 +2678,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2305
2678
  let rgb = fg * a + bgc * (1.0 - a);
2306
2679
  return vec4<f32>(rgb, 1.0);
2307
2680
  }
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
2681
+ \`;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
2682
  // (image, alpha). Used by CompositorBlur to skip the final full-res upsample
2310
2683
  // in the blur pyramid and let this shader's own per-pixel scan do the
2311
2684
  // expansion (the work is already happening here for the composite anyway).
@@ -2370,7 +2743,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2370
2743
  let rgb = fg * a + bgc * (1.0 - a);
2371
2744
  return vec4<f32>(rgb, 1.0);
2372
2745
  }
2373
- \`;var mr=\`enable f16;
2746
+ \`;var Or=\`enable f16;
2374
2747
 
2375
2748
  // f16 storage variant of composite_image_bilinear. bg is at a smaller
2376
2749
  // resolution and is bilinearly sampled to match (image, alpha) at full res.
@@ -2431,7 +2804,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2431
2804
  let rgb = fg * a + bgc * (1.0 - a);
2432
2805
  return vec4<f32>(rgb, 1.0);
2433
2806
  }
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
2807
+ \`;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
2808
  // swapchain texture with no alpha math and no background. Used by RenderOp
2436
2809
  // when the renderer is in disabled state, so the output canvas reflects
2437
2810
  // the unmodified input frame instead of a stale matted result.
@@ -2469,7 +2842,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2469
2842
  let i = y * params.width + x;
2470
2843
  return vec4<f32>(image[i].rgb, 1.0);
2471
2844
  }
2472
- \`;var hr=\`enable f16;
2845
+ \`;var Ar=\`enable f16;
2473
2846
 
2474
2847
  // Passthrough "compositor" \\u2014 f16 variant. Image is stored as f16; values
2475
2848
  // promote to f32 on read and the fragment writes f32 to the canvas
@@ -2505,7 +2878,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
2505
2878
  let i = y * params.width + x;
2506
2879
  return vec4<f32>(vec3<f32>(image[i].rgb), 1.0);
2507
2880
  }
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
2881
+ \`;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
2882
  // vec4<f32> output buffer at the target resolution. Used for ImageBitmap
2510
2883
  // sources, which are uploaded into a persistent staging texture via
2511
2884
  // copyExternalImageToTexture before each dispatch.
@@ -2535,7 +2908,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2535
2908
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
2536
2909
  output_buf[y * params.out_w + x] = rgba;
2537
2910
  }
2538
- \`;var _r=\`enable f16;
2911
+ \`;var Rr=\`enable f16;
2539
2912
 
2540
2913
  // Input op \\u2014 f16 storage variant. Source is sampled as vec4<f32>; only the
2541
2914
  // store is demoted to vec4<f16>.
@@ -2565,7 +2938,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2565
2938
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
2566
2939
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
2567
2940
  }
2568
- \`;var br=\`// Input op \\u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
2941
+ \`;var Hr=\`// Input op \\u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
2569
2942
  // the NHWC vec4<f32> output buffer at the target resolution. Used when the
2570
2943
  // caller passes a VideoFrame to setSource(); requires importExternalTexture
2571
2944
  // to be called in the same task as the dispatch (the texture is invalidated
@@ -2596,7 +2969,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2596
2969
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
2597
2970
  output_buf[y * params.out_w + x] = rgba;
2598
2971
  }
2599
- \`;var xr=\`enable f16;
2972
+ \`;var zr=\`enable f16;
2600
2973
 
2601
2974
  // Input op \\u2014 texture_external + f16 storage. Sample in f32, store as f16.
2602
2975
 
@@ -2625,12 +2998,12 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2625
2998
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
2626
2999
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
2627
3000
  }
2628
- \`;var xi=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()");xi(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"?xr: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 vi=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,O=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");this.bytesPerElement=e==="f16"?2:4;let o=r.getContext("webgpu");if(!o)throw new Error("Failed to get WebGPU context from canvas");this.canvasContext=o,this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.canvasContext.configure({device:t,format:this.canvasFormat,alphaMode:"premultiplied"}),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 xe(this,a,n,u,p),UpFinal:(a,n,u)=>new ve(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)=>{let p=new Ce(this,a,n,u);return{run:()=>{p.setOutput(this.getCurrentDisplayTexture()),p.run()}}},CompositeImage:(a,n,u)=>{let p=new We(this,a,n,u);return{run:()=>{p.setOutput(this.getCurrentDisplayTexture()),p.run()}}},CompositeImageBilinear:(a,n,u)=>{let p=new Pe(this,a,n,u);return{run:()=>{p.setOutput(this.getCurrentDisplayTexture()),p.run()}}},CompositePassthrough:a=>{let n=new Ge(this,a);return{run:()=>{n.setOutput(this.getCurrentDisplayTexture()),n.run()}}}}}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(){return this.canvasContext.getCurrentTexture()}tensor(t,r,e,o){let n=t*r*e*this.bytesPerElement,u=this.device.createBuffer({size:n,usage:vi,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(D(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"?D(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 yi=\`#version 300 es
3001
+ \`;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
3002
  const vec2 VERTS[6] = vec2[6](
2630
3003
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
2631
3004
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
2632
3005
  );
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,yi),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 vr=\`#version 300 es
3006
+ 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
3007
  // Conv2d \\u2014 handles all variants: 1\\xD71 (pointwise), 3\\xD73, 5\\xD75, strided, BN-fused.
2635
3008
  //
2636
3009
  // Tensor layout: NHWC vec4 \\u2014 texture dimensions (W * C/4, H).
@@ -2663,7 +3036,7 @@ uniform int u_kernel_w;
2663
3036
  uniform int u_stride;
2664
3037
  uniform int u_pad_top;
2665
3038
  uniform int u_pad_left;
2666
- uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu
3039
+ uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu, 3 = leaky(0.1)
2667
3040
 
2668
3041
  out vec4 fragColor;
2669
3042
 
@@ -2703,10 +3076,80 @@ void main() {
2703
3076
 
2704
3077
  if (u_activation == 1) result = clamp(result, 0.0, 6.0);
2705
3078
  else if (u_activation == 2) result = max(result, vec4(0.0));
3079
+ else if (u_activation == 3) result = max(result, 0.1 * result);
3080
+
3081
+ fragColor = result;
3082
+ }
3083
+ \`;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
3084
+ // ConvTranspose2d \\u2014 gather form. Identical texture layouts + mat4 weight
3085
+ // semantics as conv2d.glsl; only the spatial mapping differs:
3086
+ // in_y = (y_out + pad - ky) / stride (must divide evenly + be in bounds)
3087
+ // No explicit kernel flip \\u2014 the (y_out + pad - ky) indexing carries it.
3088
+
3089
+ precision highp float;
3090
+ precision highp int;
3091
+
3092
+ uniform sampler2D u_input; // (in_W * in_C_groups, in_H)
3093
+ uniform sampler2D u_weights; // (in_C_groups * 4, K\\xB2 * out_C_groups)
3094
+ uniform sampler2D u_bias; // (out_C_groups, 1)
3095
+
3096
+ uniform int u_in_w;
3097
+ uniform int u_in_h;
3098
+ uniform int u_in_c_groups;
3099
+ uniform int u_out_c_groups;
3100
+ uniform int u_kernel_h;
3101
+ uniform int u_kernel_w;
3102
+ uniform int u_stride;
3103
+ uniform int u_pad_top;
3104
+ uniform int u_pad_left;
3105
+ uniform int u_activation; // 0 = none, 1 = relu6, 2 = relu, 3 = leaky(0.1)
3106
+
3107
+ out vec4 fragColor;
3108
+
3109
+ void main() {
3110
+ int fx = int(gl_FragCoord.x);
3111
+ int fy = int(gl_FragCoord.y);
3112
+ int x_out = fx / u_out_c_groups;
3113
+ int y_out = fy;
3114
+ int o_group = fx - x_out * u_out_c_groups;
3115
+
3116
+ vec4 result = texelFetch(u_bias, ivec2(o_group, 0), 0);
3117
+
3118
+ for (int ky = 0; ky < u_kernel_h; ky++) {
3119
+ for (int kx = 0; kx < u_kernel_w; kx++) {
3120
+ int iy_num = y_out + u_pad_top - ky;
3121
+ int ix_num = x_out + u_pad_left - kx;
3122
+ if (iy_num < 0 || ix_num < 0) continue;
3123
+ if ((iy_num % u_stride) != 0 || (ix_num % u_stride) != 0) continue;
3124
+ int in_y = iy_num / u_stride;
3125
+ int in_x = ix_num / u_stride;
3126
+ if (in_y >= u_in_h || in_x >= u_in_w) continue;
3127
+
3128
+ int z = ky * u_kernel_w + kx;
3129
+ int w_row = z * u_out_c_groups + o_group;
3130
+
3131
+ for (int i = 0; i < u_in_c_groups; i++) {
3132
+ vec4 in_val = texelFetch(u_input, ivec2(in_x * u_in_c_groups + i, in_y), 0);
3133
+
3134
+ int base = i * 4;
3135
+ mat4 w = mat4(
3136
+ texelFetch(u_weights, ivec2(base, w_row), 0),
3137
+ texelFetch(u_weights, ivec2(base + 1, w_row), 0),
3138
+ texelFetch(u_weights, ivec2(base + 2, w_row), 0),
3139
+ texelFetch(u_weights, ivec2(base + 3, w_row), 0)
3140
+ );
3141
+ result += w * in_val;
3142
+ }
3143
+ }
3144
+ }
3145
+
3146
+ if (u_activation == 1) result = clamp(result, 0.0, 6.0);
3147
+ else if (u_activation == 2) result = max(result, vec4(0.0));
3148
+ else if (u_activation == 3) result = max(result, 0.1 * result);
2706
3149
 
2707
3150
  fragColor = result;
2708
3151
  }
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",vr);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),v=this.makeTexture(_,p*4,a.kernel*a.kernel*l),y=this.makeTexture(g,l,1),T=u*l,W=this.makeTexture(null,T,n);this.output={h:n,w:u,c:a.outChannels,texture:W,texW:T,texH:n},this.inputs=[e],this.weights=[],this.samplers=[{name:"u_input",texture:e.texture},{name:"u_weights",texture:v},{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
3152
+ \`;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
3153
  // Depthwise Conv2d \\u2014 groups = in_channels (each channel convolved independently).
2711
3154
  //
2712
3155
  // Weight layout: (C_groups, K\\xB2) RGBA32F texture \\u2014 contrast with conv2d which uses mat4.
@@ -2763,7 +3206,7 @@ void main() {
2763
3206
 
2764
3207
  fragColor = result;
2765
3208
  }
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),v=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:v}],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
3209
+ \`;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
3210
  // Element-wise add \\u2014 both inputs and output share the same texture dimensions.
2768
3211
  // Works for any 2D layout; used here with a flat (nVec4, 1) texture.
2769
3212
 
@@ -2778,7 +3221,7 @@ void main() {
2778
3221
  ivec2 fc = ivec2(gl_FragCoord.xy);
2779
3222
  fragColor = texelFetch(u_input_a, fc, 0) + texelFetch(u_input_b, fc, 0);
2780
3223
  }
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
3224
+ \`;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
3225
  // Element-wise sigmoid \\u2014 works on any texture layout (flat or spatial).
2783
3226
 
2784
3227
  precision highp float;
@@ -2791,7 +3234,7 @@ void main() {
2791
3234
  vec4 x = texelFetch(u_input, ivec2(gl_FragCoord.xy), 0);
2792
3235
  fragColor = 1.0 / (1.0 + exp(-x));
2793
3236
  }
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
3237
+ \`;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
2795
3238
  // Element-wise tanh \\u2014 used by ConvGRU candidate activation.
2796
3239
  // Layout-agnostic (flat or spatial); GLSL tanh is element-wise on vec4.
2797
3240
 
@@ -2804,7 +3247,7 @@ out vec4 fragColor;
2804
3247
  void main() {
2805
3248
  fragColor = tanh(texelFetch(u_input, ivec2(gl_FragCoord.xy), 0));
2806
3249
  }
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
3250
+ \`;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
2808
3251
  // Element-wise multiply \\u2014 used in ConvGRU for r \\u2299 h_prev.
2809
3252
  // Same shape constraint as add.glsl.
2810
3253
 
@@ -2815,11 +3258,102 @@ uniform sampler2D u_input_b;
2815
3258
 
2816
3259
  out vec4 fragColor;
2817
3260
 
2818
- void main() {
2819
- ivec2 fc = ivec2(gl_FragCoord.xy);
2820
- fragColor = texelFetch(u_input_a, fc, 0) * texelFetch(u_input_b, fc, 0);
3261
+ void main() {
3262
+ ivec2 fc = ivec2(gl_FragCoord.xy);
3263
+ fragColor = texelFetch(u_input_a, fc, 0) * texelFetch(u_input_b, fc, 0);
3264
+ }
3265
+ \`;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
3266
+ // Bilinear gather-warp. out[p] = sample(source, p + flow_scale\\xB7flow[p].xy),
3267
+ // edge-clamped. Source + flow are 4-ch (1 group), same resolution; flow in .xy.
3268
+
3269
+ precision highp float;
3270
+ precision highp int;
3271
+
3272
+ uniform sampler2D u_source; // (W, H)
3273
+ uniform sampler2D u_flow; // (W, H), flow in .xy
3274
+ uniform int u_w;
3275
+ uniform int u_h;
3276
+ uniform float u_flow_scale;
3277
+
3278
+ out vec4 fragColor;
3279
+
3280
+ vec4 samp(int x, int y) {
3281
+ int cx = clamp(x, 0, u_w - 1);
3282
+ int cy = clamp(y, 0, u_h - 1);
3283
+ return texelFetch(u_source, ivec2(cx, cy), 0);
3284
+ }
3285
+
3286
+ void main() {
3287
+ int x = int(gl_FragCoord.x);
3288
+ int y = int(gl_FragCoord.y);
3289
+
3290
+ vec2 f = texelFetch(u_flow, ivec2(x, y), 0).xy;
3291
+ float sx = clamp(float(x) + u_flow_scale * f.x, 0.0, float(u_w - 1));
3292
+ float sy = clamp(float(y) + u_flow_scale * f.y, 0.0, float(u_h - 1));
3293
+
3294
+ int x0 = int(floor(sx));
3295
+ int y0 = int(floor(sy));
3296
+ float tx = sx - float(x0);
3297
+ float ty = sy - float(y0);
3298
+
3299
+ vec4 top = mix(samp(x0, y0), samp(x0 + 1, y0), tx);
3300
+ vec4 bot = mix(samp(x0, y0 + 1), samp(x0 + 1, y0 + 1), tx);
3301
+ fragColor = mix(top, bot, ty);
3302
+ }
3303
+ \`;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
3304
+ // Flow-gated temporal stabilizer. Per pixel:
3305
+ // env = max(|flow.xy|, release\\xB7envPrev.y) peak-hold
3306
+ // g = max(clamp((env - tLo)/(tHi - tLo), 0, 1), leak)
3307
+ // out = vec4((g\\xB7pred + (1-g)\\xB7ref).x, env, 0, 0)
3308
+
3309
+ precision highp float;
3310
+ precision highp int;
3311
+
3312
+ uniform sampler2D u_flow;
3313
+ uniform sampler2D u_pred;
3314
+ uniform sampler2D u_ref;
3315
+ uniform sampler2D u_env_prev;
3316
+ uniform int u_w;
3317
+ uniform int u_h;
3318
+ uniform float u_t_lo;
3319
+ uniform float u_t_hi;
3320
+ uniform float u_leak;
3321
+ uniform float u_release;
3322
+ uniform float u_t_div;
3323
+ uniform float u_div_scale;
3324
+ uniform int u_step_x;
3325
+ uniform int u_step_y;
3326
+
3327
+ out vec4 fragColor;
3328
+
3329
+ void main() {
3330
+ int x = int(gl_FragCoord.x);
3331
+ int y = int(gl_FragCoord.y);
3332
+
3333
+ float mag = length(texelFetch(u_flow, ivec2(x, y), 0).xy);
3334
+ float envPrev = texelFetch(u_env_prev, ivec2(x, y), 0).y;
3335
+ float env = max(mag, u_release * envPrev);
3336
+
3337
+ // Flow divergence over a \\xB1step finite-difference (clamped to the edges).
3338
+ int xr = min(x + u_step_x, u_w - 1);
3339
+ int xl = max(x - u_step_x, 0);
3340
+ int yd = min(y + u_step_y, u_h - 1);
3341
+ int yu = max(y - u_step_y, 0);
3342
+ float dfx = texelFetch(u_flow, ivec2(xr, y), 0).x - texelFetch(u_flow, ivec2(xl, y), 0).x;
3343
+ float dfy = texelFetch(u_flow, ivec2(x, yd), 0).y - texelFetch(u_flow, ivec2(x, yu), 0).y;
3344
+ float divg = abs(dfx + dfy);
3345
+
3346
+ float gMag = clamp((env - u_t_lo) / max(u_t_hi - u_t_lo, 1e-3), 0.0, 1.0);
3347
+ float gDiv = clamp((divg - u_t_div) / max(u_div_scale, 1e-3), 0.0, 1.0);
3348
+ float g = max(max(gMag, gDiv), u_leak);
3349
+
3350
+ float pred = texelFetch(u_pred, ivec2(x, y), 0).x;
3351
+ float refv = texelFetch(u_ref, ivec2(x, y), 0).x;
3352
+ float stab = g * pred + (1.0 - g) * refv;
3353
+
3354
+ fragColor = vec4(stab, env, 0.0, 0.0);
2821
3355
  }
2822
- \`;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",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
3356
+ \`;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
3357
  // Bilinear upsample (arbitrary scale) \\u2014 align_corners=False.
2824
3358
  //
2825
3359
  // Hardware texture filtering can't be used: adjacent texels in x belong to
@@ -2870,7 +3404,21 @@ void main() {
2870
3404
 
2871
3405
  fragColor = mix(mix(v00, v10, fx), mix(v01, v11, fx), fy);
2872
3406
  }
2873
- \`;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",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
3407
+ \`;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
3408
+ // Top-left crop: the output viewport is smaller than the input texture, so reading
3409
+ // the same fragment coord yields the top-left subregion (channel groups packed in
3410
+ // the x axis line up because group count is unchanged).
3411
+
3412
+ precision highp float;
3413
+ precision highp int;
3414
+
3415
+ uniform sampler2D u_input;
3416
+ out vec4 fragColor;
3417
+
3418
+ void main() {
3419
+ fragColor = texelFetch(u_input, ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y)), 0);
3420
+ }
3421
+ \`;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
3422
  // Bicubic upsample (arbitrary scale) \\u2014 Keys cubic, a=-0.75 (PyTorch default
2875
3423
  // for mode='bicubic', align_corners=False).
2876
3424
  //
@@ -2930,7 +3478,7 @@ void main() {
2930
3478
  }
2931
3479
  fragColor = acc;
2932
3480
  }
2933
- \`;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",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
3481
+ \`;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
3482
  // Channel concat \\u2014 concatenates two NHWC textures along the channel dimension.
2935
3483
  // Both inputs must share the same spatial dimensions (W, H). Channel counts are
2936
3484
  // multiples of 4 so each "group" is one vec4 texel.
@@ -2963,7 +3511,7 @@ void main() {
2963
3511
  fragColor = texelFetch(u_input_b, ivec2(x_spatial * u_b_c_groups + c_b, y), 0);
2964
3512
  }
2965
3513
  }
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
3514
+ \`;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
3515
  // Bilinear upsample + sigmoid fused \\u2014 sigmoid applied at write time, no intermediate buffer.
2968
3516
  // See bilinear_upsample.glsl for the manual 4-tap blend rationale.
2969
3517
  //
@@ -3013,7 +3561,7 @@ void main() {
3013
3561
  vec4 result = mix(mix(v00, v10, fx), mix(v01, v11, fx), fy);
3014
3562
  fragColor = 1.0 / (1.0 + exp(-result));
3015
3563
  }
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
3564
+ \`;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
3565
  // Bilinear upsample (input_a) + channel concat (with input_b) fused.
3018
3566
  // input_a is the decoder tensor at small spatial res (in_h \\xD7 in_w), bilinearly resized to (out_h \\xD7 out_w).
3019
3567
  // input_b is the encoder skip feature already at output resolution.
@@ -3071,7 +3619,7 @@ void main() {
3071
3619
  fragColor = texelFetch(u_input_b, ivec2(x_out * u_b_c_groups + c_b, y_out), 0);
3072
3620
  }
3073
3621
  }
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
3622
+ \`;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
3623
  // Bilinear upsample + 1\\xD71 pointwise conv fused.
3076
3624
  // For each output pixel + out group, bilinearly samples each in_group from input,
3077
3625
  // applies the 1\\xD71 conv weight, and writes the activated result.
@@ -3148,7 +3696,7 @@ void main() {
3148
3696
 
3149
3697
  fragColor = result;
3150
3698
  }
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
3699
+ \`;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
3700
  // Conv2d + skip add fused \\u2014 identical to conv2d.glsl with a skip texture added at write time.
3153
3701
  // See conv2d.glsl for tensor/weight layout details.
3154
3702
 
@@ -3212,7 +3760,7 @@ void main() {
3212
3760
 
3213
3761
  fragColor = result + texelFetch(u_skip, ivec2(fx, fy), 0);
3214
3762
  }
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),v=d(a.bias),y=this.makeTexture(g,l*4,n.kernel*n.kernel*c),T=this.makeTexture(v,c,1),W=p*c,z=this.makeTexture(null,W,u);this.output={h:u,w:p,c:n.outChannels,texture:z,texW:W,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=[W,u]}};var Fr=\`#version 300 es
3763
+ \`;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
3764
  // proj_residual: bespoke 1\\xD71 conv (no activation) + residual add, fused.
3217
3765
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation. Both
3218
3766
  // inputs share the same spatial resolution. See conv2d.glsl for the weight
@@ -3254,7 +3802,7 @@ void main() {
3254
3802
 
3255
3803
  fragColor = result + texelFetch(u_skip, ivec2(fx, fy), 0);
3256
3804
  }
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,v=this.makeTexture(null,g,e.h);this.output={h:e.h,w:e.w,c:n.outChannels,texture:v,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
3805
+ \`;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
3806
  // concat_conv2d: fuses [concat(a, b) \\u2192 conv 3\\xD73 (pad 1) \\u2192 relu6] into one pass.
3259
3807
  // Both inputs already at output resolution. Weight cols [0, a_groups) read a,
3260
3808
  // [a_groups, I) read b. Weight texture layout matches conv2d.glsl
@@ -3315,7 +3863,7 @@ void main() {
3315
3863
 
3316
3864
  fragColor = clamp(result, 0.0, 6.0);
3317
3865
  }
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),v=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:v}],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 Ir=\`#version 300 es
3866
+ \`;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
3867
  // gates_fused: ConvGRU z + r gates, fused. Production config (c_up=2,
3320
3868
  // recurrent=1). u_in (.x=a, .y=b), h_prev (.x). weights 9 vec4 =
3321
3869
  // (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 +3906,7 @@ void main() {
3358
3906
  float r = 1.0 / (1.0 + exp(-r_pre));
3359
3907
  fragColor = vec4(z, r, 0.0, 0.0);
3360
3908
  }
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",Ir);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 Dr=\`#version 300 es
3909
+ \`;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
3910
  // cand_update_fused: ConvGRU candidate + state update + output, fused.
3363
3911
  // Production config (c_up=2, recurrent=1). u_in (.x=a, .y=b), h_prev (.x),
3364
3912
  // gates_out (.x=z, .y=r). weights 9 vec4 (.xy = b_w, rh_w) in a (9,1) texture.
@@ -3406,7 +3954,7 @@ void main() {
3406
3954
  float b_out = u_cur.y + gamma * h_new;
3407
3955
  fragColor = vec4(u_cur.x, b_out, h_new, 0.0);
3408
3956
  }
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",Dr);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 Or=\`#version 300 es
3957
+ \`;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
3958
  // conv_expand: bespoke N\\u21922 conv 3\\xD73 (pad 1) + relu (wrapper expand_feat).
3411
3959
  // Input N ch (in_groups vec4); output 2ch in .xy (.zw = 0). Weights: 9 *
3412
3960
  // in_groups mat4x2 (8 floats each, col-major c0r0,c0r1,...,c3r0,c3r1) in a
@@ -3449,7 +3997,7 @@ void main() {
3449
3997
 
3450
3998
  fragColor = vec4(max(result, vec2(0.0)), 0.0, 0.0); // expand_feat is F.relu
3451
3999
  }
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",Or);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
4000
+ \`;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
4001
  // cat_conv_6to2: fused concat(u[2], d[4]) \\u2192 6\\u21922 conv 3\\xD73 (pad 1) + relu
3454
4002
  // (E up1_combine). Channel order v3a=(u.x,u.y,d.x), v3b=d.yzw. weights = 9*2
3455
4003
  // mat3x2 (6 floats each, col-major) in a 1-row (27-texel) texture.
@@ -3496,7 +4044,7 @@ void main() {
3496
4044
 
3497
4045
  fragColor = vec4(max(result, vec2(0.0)), 0.0, 0.0); // up1_combine is F.relu
3498
4046
  }
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
4047
+ \`;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
4048
  // down_adapter: stride-N 3\\xD73 conv (mat4x4, 4\\u21924) + relu, then 1\\xD71 adapter
3501
4049
  // (4\\u21923, last row 0). down_w = 9 mat4x4 (1-row, 36 texels); adapt_w = 1 mat4x4
3502
4050
  // (4 texels). Output 3ch in .xyz (.w=0). Symmetric pad. Weight packing matches
@@ -3548,7 +4096,7 @@ void main() {
3548
4096
  a.z = awf(2) * d.x + awf(6) * d.y + awf(10) * d.z + awf(14) * d.w + ab.z;
3549
4097
  fragColor = vec4(a.xyz, 0.0);
3550
4098
  }
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),v=p,y=this.makeTexture(null,v,u);this.output={h:u,w:p,c:4,texture:y,texW:v,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=[v,u]}};var Mr=\`#version 300 es
4099
+ \`;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
4100
  // up_final: cat(u[2], rgb[3]) \\u2192 conv 3\\xD73 5\\u21921 \\u2192 sigmoid (A/B alpha head).
3553
4101
  // weights 18 vec4 (1-row): [kpos]=(w0,w1,0,0) for u, [9+kpos]=(w2,w3,w4,0) rgb.
3554
4102
 
@@ -3586,7 +4134,7 @@ void main() {
3586
4134
 
3587
4135
  fragColor = vec4(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
3588
4136
  }
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
4137
+ \`;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
4138
  // up_final_skip (C/D alpha head): cat(u[2], d_full[4], rgb[3]) \\u2192 conv 9\\u21921 \\u2192
3591
4139
  // sigmoid. Weights = 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u;
3592
4140
  // [kpos*3+1]=(w2..w5) d_full; [kpos*3+2]=(w6,w7,w8,0) rgb.
@@ -3629,7 +4177,7 @@ void main() {
3629
4177
 
3630
4178
  fragColor = vec4(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
3631
4179
  }
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
4180
+ \`;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
4181
  // Composite an RGBA image over a solid background color, gated by a
3634
4182
  // 1-channel alpha mask. Output: premultiplied RGBA.
3635
4183
  //
@@ -3660,12 +4208,12 @@ void main() {
3660
4208
  vec3 rgb = fg * a + u_bgColor * (1.0 - a);
3661
4209
  fragColor = vec4(rgb, 1.0);
3662
4210
  }
3663
- \`;var $i=\`#version 300 es
4211
+ \`;var Da=\`#version 300 es
3664
4212
  const vec2 VERTS[6] = vec2[6](
3665
4213
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3666
4214
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3667
4215
  );
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,$i),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
4216
+ 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
4217
  // Same as composite_solid but bg is a texture (NHWC vec4 tensor) instead of
3670
4218
  // a uniform color. Caller invariants: image, alpha, bg all share h \\xD7 w, and
3671
4219
  // canvas dimensions match.
@@ -3691,12 +4239,12 @@ void main() {
3691
4239
  vec3 rgb = fg * a + bg * (1.0 - a);
3692
4240
  fragColor = vec4(rgb, 1.0);
3693
4241
  }
3694
- \`;var ji=\`#version 300 es
4242
+ \`;var Ia=\`#version 300 es
3695
4243
  const vec2 VERTS[6] = vec2[6](
3696
4244
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3697
4245
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3698
4246
  );
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,ji),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
4247
+ 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
4248
  // Like composite_image but bg is bilinearly sampled \\u2014 bg is at a smaller
3701
4249
  // resolution than (image, alpha) at canvas h \\xD7 w. Used by CompositorBlur to
3702
4250
  // skip the final full-res upsample in the blur pyramid.
@@ -3745,12 +4293,12 @@ void main() {
3745
4293
  vec3 rgb = fg * a + bg * (1.0 - a);
3746
4294
  fragColor = vec4(rgb, 1.0);
3747
4295
  }
3748
- \`;var Ki=\`#version 300 es
4296
+ \`;var Ma=\`#version 300 es
3749
4297
  const vec2 VERTS[6] = vec2[6](
3750
4298
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3751
4299
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3752
4300
  );
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,Ki),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
4301
+ 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
4302
  // Passthrough "compositor": writes the image directly to the canvas
3755
4303
  // (default framebuffer). No alpha math, no background. Used by RenderOp
3756
4304
  // when the renderer is in disabled state.
@@ -3773,12 +4321,12 @@ void main() {
3773
4321
  vec3 rgb = texelFetch(u_image, px, 0).rgb;
3774
4322
  fragColor = vec4(rgb, 1.0);
3775
4323
  }
3776
- \`;var Qi=\`#version 300 es
4324
+ \`;var Ha=\`#version 300 es
3777
4325
  const vec2 VERTS[6] = vec2[6](
3778
4326
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3779
4327
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3780
4328
  );
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,Qi),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
4329
+ 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
4330
  precision highp float;
3783
4331
 
3784
4332
  // Input op \\u2014 bilinear-sample a source texture (RGBA8 unorm uploaded from an
@@ -3796,21 +4344,20 @@ void main() {
3796
4344
  vec2 uv = (gl_FragCoord.xy + vec2(0.5)) / vec2(float(u_out_w), float(u_out_h));
3797
4345
  fragColor = texture(u_src, uv);
3798
4346
  }
3799
- \`;var Zi=\`#version 300 es
4347
+ \`;var Va=\`#version 300 es
3800
4348
  const vec2 VERTS[6] = vec2[6](
3801
4349
  vec2(-1.0,-1.0), vec2(1.0,-1.0), vec2(-1.0,1.0),
3802
4350
  vec2(-1.0,1.0), vec2(1.0,-1.0), vec2(1.0,1.0)
3803
4351
  );
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,Zi),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 Ie(this,o,a),BilinearUpsample:(o,a)=>new De(this,o,a),BicubicUpsample:(o,a)=>new Oe(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")}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):D(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),D(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 O.isAvailable()){let p=s.dtype==="f16"&&!await O.hasF16Support()?"f32":s.dtype,l=a();try{let c=await O.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,ea=3,Kr=10,ta=30,F=U("autotune");async function Yr(s,t=ta){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 ia(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 ra(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 oa(){let s=new Proxy({},{get:()=>s});return s}async function ia(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=ra(s),a=o.tensor(r.baseRes.h,r.baseRes.w,4),n=new e(o,a,oa());for(let c=0;c<ea;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 aa=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||aa.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 B=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 na(t,r);C("cmd ok:",t),fa(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 na(s,t){switch(s){case"init":return sa(t);case"startRender":return ua(t.weights);case"setBackground":return pa(t);case"setEnabled":return la(t.enabled);case"setPreset":return ca(t);case"getStats":return B?.getStats()??null;case"destroy":return da();default:throw new Error(\`unknown cmd: \${s}\`)}}async function sa(s){if(lt(!!s.debug),C("handleInit: start; topology=",s.topology,"preset=",s.preset,"backend=",s.backend,"dtype=",s.dtype),B)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"),B=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,B,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 ua(s){if(C("handleStartRender: start; weights bytes:",s.byteLength),!B||!ot)throw new Error("handleStartRender: handleInit not completed");C("handleStartRender: attaching network via setPreset\\u2026"),B.setPreset(ot,s),C("handleStartRender: ready (effect mode active)"),H("ready",void 0)}async function pa(s){B?.setBackground(s)}async function la(s){B?.setEnabled(s)}async function ca(s){if(!B)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)??ma(s.preset):s.preset;return B.setPreset(t,s.weights),{resolvedPreset:t}}async function da(){A?.abort(),A=null,B?.destroy(),B=null,ot=null}function ma(s){throw new Error(\`handleSetPreset: unknown preset '\${s}'\`)}function fa(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 Ih(s){H("stats",s)}export{Ih as emitStats};
3805
- `;var y=x("pipeline");function Qt(){{let a=new Blob([fe],{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 he=class{stream;ready;controller;worker;inputCleanup;outputCleanup;adaptive=null;bgCleanup=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 A(this.worker),this.ready=new Promise((l,f)=>{this.controller.addPersistentListener("ready",()=>{y("ready handler invoked; resolving .ready"),r.onReady?.(),l();}),this.controller.addPersistentListener("error",h=>{console.error(`[longpipe/pipeline] error (${h.source}):`,h.message),h.recoverable||f(new Error(h.message)),r.onError?.(h);});});let s={topology:n,preset:r.preset,enabled:r.enabled,backend:"auto",dtype:"f16",canvasSize:o,debug:r.debug,...i.initFields,...u.initFields},d=[...i.transferList,...u.transferList];this.bootstrap(s,r.background,d,r.weightsBaseUrl,r.adaptive,r.onError);}async bootstrap(t,e,r,n,i,o){try{y("normalizing background\u2026");let u=await de(e);this.bgCleanup=u.cleanup??null;let s={...t,background:u.background},d=[...r,...u.transferList??[]];y("sending init\u2026");let l=await this.controller.sendMessage("init",s,d);y("init resolved:",l);let f=Ee(n,l.resolvedPreset.model);y("fetching weights:",f);let h=await fetch(f);if(!h.ok)throw new Error(`weights fetch failed: ${h.status} ${f}`);let v=await h.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:l.resolvedBackend,initialModel:l.resolvedPreset.model,weightsBaseUrl:n,buildWeightsUrl:Ee,getStats:()=>this.getStats(),swapPreset:async(I,pe)=>{await this.controller.sendMessage("setPreset",{preset:I,weights:pe},[pe]);},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 de(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});}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.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 d=r&8388607|8388608,l=14-n,f=d>>>l,h=d>>>l-1&1,v=(d&(1<<l-1)-1)!==0?1:0;return h&&(v||f&1)&&(f+=1),e|f}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.
4352
+ 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};
4353
+ `;var y=v("pipeline");function cr(){{let a=new Blob([ge],{type:"application/javascript"}),t=URL.createObjectURL(a),e=new Worker(t,{type:"module"});return URL.revokeObjectURL(t),e}}var dr="https://cdn.longpipe.dev/models/v/0.0.3/",fr={background:"blur",preset:"auto",weightsBaseUrl:dr,audio:"passthrough",enabled:true,adaptive:true,debug:false},Me={w:1280,h:720};function hr(a,t){if(t)return t;let r=a.getVideoTracks()[0]?.getSettings()??{};return {w:r.width||Me.w,h:r.height||Me.h}}function ze(a,t,e){let r=e==="f16"?".f16.bin":".bin";return `${a.replace(/\/$/,"")}/model_${t}${r}`}async function De(a,t,e){if(e==="f16"){let i=await fetch(ze(a,t,"f16"));if(i.ok)return i.arrayBuffer()}let r=ze(a,t,"f32"),n=await fetch(r);if(!n.ok)throw new Error(`weights fetch failed: ${n.status} ${r}`);return n.arrayBuffer()}var _e=class{stream;ready;controller;worker;inputCleanup;outputCleanup;adaptive=null;bgCleanup=null;previewBgCleanup=null;constructor(t,e){let r={...fr,...e};ye(r.debug);let n=Ue(),i=Ge(n.input,t),o=hr(t,r.outputResolution),s=Oe(n.output,o);this.inputCleanup=i.cleanup,this.outputCleanup=s.cleanup,this.stream=We(s.videoTrack,t,r.audio),s.startPassthrough?.(t),this.worker=cr(),this.controller=new A(this.worker),this.ready=new Promise((c,f)=>{this.controller.addPersistentListener("ready",()=>{y("ready handler invoked; resolving .ready"),r.onReady?.(),c();}),this.controller.addPersistentListener("error",h=>{console.error(`[longpipe/pipeline] error (${h.source}):`,h.message),h.recoverable||f(new Error(h.message)),r.onError?.(h);});});let u={topology:n,preset:r.preset,enabled:r.enabled,backend:"auto",dtype:"f16",canvasSize:o,debug:r.debug,...i.initFields,...s.initFields},l=[...i.transferList,...s.transferList];this.bootstrap(u,r.background,l,r.weightsBaseUrl,r.adaptive,r.onError);}async bootstrap(t,e,r,n,i,o){try{y("normalizing background\u2026");let s=await G(e);this.bgCleanup=s.cleanup??null;let u={...t,background:s.background},l=[...r,...s.transferList??[]];y("sending init\u2026");let c=await this.controller.sendMessage("init",u,l);y("init resolved:",c),y("fetching weights:",c.resolvedPreset.model,c.resolvedDtype);let f=await De(n,c.resolvedPreset.model,c.resolvedDtype);y("weights bytes:",f.byteLength),y("sending startRender\u2026"),await this.controller.sendMessage("startRender",{weights:f},[f]),y("startRender resolved; awaiting first frame"),u.preset==="auto"&&i&&(this.adaptive=new S({backendKind:c.resolvedBackend,initialModel:c.resolvedPreset.model,fetchWeights:h=>De(n,h,c.resolvedDtype),getStats:()=>this.getStats(),swapPreset:async(h,x)=>{await this.controller.sendMessage("setPreset",{preset:h,weights:x},[x]);},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 G(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 G(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 gr(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,f=l>>>c,h=l>>>c-1&1,x=(l&(1<<c-1)-1)!==0?1:0;return h&&(x||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 me(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 He(a){let t=new Uint16Array(a.length);for(let e=0;e<a.length;e++)t[e]=gr(a[e]);return t}function be(a){let t=new Float32Array(a.length);for(let e=0;e<a.length;e++)t[e]=me(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 Re=`// Conv2d, output-channel-blocked (K=2) \u2014 drop-in replacement for conv2d.wgsl.
3806
4354
  //
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).
4355
+ // Identical math, layout, and output to conv2d.wgsl, but each thread computes 2
4356
+ // output channel-groups (8 channels) for one pixel, loading each input vec4 ONCE
4357
+ // and reusing it across both groups' mat4x4 weight blocks in registers. Half the
4358
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
4359
+ // identical to conv2d.wgsl (\u22641 ULP from FMA contraction). Dispatch
4360
+ // ceil(out_groups / 2) in z (see conv2d.ts).
3814
4361
  //
3815
4362
  // Tensor layout: NHWC, channels in vec4 groups (same as conv2d.wgsl).
3816
4363
  // Weight layout: [K*K][out_groups][in_groups] array of mat4x4 (same as conv2d.wgsl).
@@ -3827,7 +4374,7 @@ struct Params {
3827
4374
  stride : u32,
3828
4375
  pad_top : u32,
3829
4376
  pad_left : u32,
3830
- activation : u32, // 0 = none, 1 = relu6, 2 = relu
4377
+ activation : u32, // 0 = none, 1 = relu6, 2 = relu, 3 = leaky
3831
4378
  }
3832
4379
 
3833
4380
  @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
@@ -3836,18 +4383,19 @@ struct Params {
3836
4383
  @group(0) @binding(3) var<uniform> params : Params;
3837
4384
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
3838
4385
 
3839
- const KB = 4u;
4386
+ const KB = 2u;
3840
4387
 
3841
4388
  fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
3842
4389
  if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
3843
4390
  if (a == 2u) { return max(v, vec4<f32>(0.0)); }
4391
+ if (a == 3u) { return max(v, 0.1 * v); } // leaky relu (slope 0.1)
3844
4392
  return v;
3845
4393
  }
3846
4394
 
3847
4395
  @compute @workgroup_size(8, 8, 1)
3848
4396
  fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3849
- let x = gid.x; // output column
3850
- let y = gid.y; // output row
4397
+ let x = gid.x; // output column
4398
+ let y = gid.y; // output row
3851
4399
  let o0 = gid.z * KB; // first output channel group
3852
4400
 
3853
4401
  if (x >= params.out_w || y >= params.out_h || o0 >= params.out_groups) {
@@ -3856,19 +4404,13 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3856
4404
 
3857
4405
  let I = params.in_groups;
3858
4406
  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.
4407
+ // Tail handling when out_groups is odd: clamp the spare lane to o0 (valid
4408
+ // index, no OOB) and just don't write it.
3861
4409
  let has1 = (o0 + 1u) < O;
3862
- let has2 = (o0 + 2u) < O;
3863
- let has3 = (o0 + 3u) < O;
3864
4410
  let o1 = select(o0, o0 + 1u, has1);
3865
- let o2 = select(o0, o0 + 2u, has2);
3866
- let o3 = select(o0, o0 + 3u, has3);
3867
4411
 
3868
4412
  var acc0 = bias_buf[o0];
3869
4413
  var acc1 = bias_buf[o1];
3870
- var acc2 = bias_buf[o2];
3871
- var acc3 = bias_buf[o3];
3872
4414
 
3873
4415
  for (var ky = 0u; ky < params.kernel_h; ky++) {
3874
4416
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -3884,14 +4426,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3884
4426
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
3885
4427
  let wb0 = z * O * I + o0 * I;
3886
4428
  let wb1 = z * O * I + o1 * I;
3887
- let wb2 = z * O * I + o2 * I;
3888
- let wb3 = z * O * I + o3 * I;
3889
4429
  for (var i = 0u; i < I; i++) {
3890
- let iv = input_buf[inB + i]; // loaded ONCE, reused across 4 groups
4430
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
3891
4431
  acc0 += weight_buf[wb0 + i] * iv;
3892
4432
  acc1 += weight_buf[wb1 + i] * iv;
3893
- acc2 += weight_buf[wb2 + i] * iv;
3894
- acc3 += weight_buf[wb3 + i] * iv;
3895
4433
  }
3896
4434
  }
3897
4435
  }
@@ -3899,15 +4437,14 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3899
4437
  let baseO = y * params.out_w * O + x * O;
3900
4438
  output_buf[baseO + o0] = act(acc0, params.activation);
3901
4439
  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
4440
  }
3905
- `;var Oe=`enable f16;
4441
+ `;var Le=`enable f16;
3906
4442
 
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.
4443
+ // Conv2d, output-channel-blocked (K=2) \u2014 full f16. Drop-in replacement for
4444
+ // conv2d_f16.wgsl. Each thread computes 2 output channel-groups for one pixel,
4445
+ // loading each input vec4 ONCE and reusing it across both weight blocks. Half the
4446
+ // register pressure of the K=4 variant (2 accumulators vs 4). Output is bit-
4447
+ // identical to conv2d_f16.wgsl. Dispatch ceil(out_groups / 2) in z.
3911
4448
 
3912
4449
  struct Params {
3913
4450
  in_h : u32,
@@ -3930,11 +4467,12 @@ struct Params {
3930
4467
  @group(0) @binding(3) var<uniform> params : Params;
3931
4468
  @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
3932
4469
 
3933
- const KB = 4u;
4470
+ const KB = 2u;
3934
4471
 
3935
4472
  fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
3936
4473
  if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
3937
4474
  if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
4475
+ if (a == 3u) { return max(v, 0.1h * v); } // leaky relu (slope 0.1)
3938
4476
  return v;
3939
4477
  }
3940
4478
 
@@ -3951,16 +4489,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3951
4489
  let I = params.in_groups;
3952
4490
  let O = params.out_groups;
3953
4491
  let has1 = (o0 + 1u) < O;
3954
- let has2 = (o0 + 2u) < O;
3955
- let has3 = (o0 + 3u) < O;
3956
4492
  let o1 = select(o0, o0 + 1u, has1);
3957
- let o2 = select(o0, o0 + 2u, has2);
3958
- let o3 = select(o0, o0 + 3u, has3);
3959
4493
 
3960
4494
  var acc0 = bias_buf[o0];
3961
4495
  var acc1 = bias_buf[o1];
3962
- var acc2 = bias_buf[o2];
3963
- var acc3 = bias_buf[o3];
3964
4496
 
3965
4497
  for (var ky = 0u; ky < params.kernel_h; ky++) {
3966
4498
  for (var kx = 0u; kx < params.kernel_w; kx++) {
@@ -3976,14 +4508,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3976
4508
  let inB = u32(in_y_s) * params.in_w * I + u32(in_x_s) * I;
3977
4509
  let wb0 = z * O * I + o0 * I;
3978
4510
  let wb1 = z * O * I + o1 * I;
3979
- let wb2 = z * O * I + o2 * I;
3980
- let wb3 = z * O * I + o3 * I;
3981
4511
  for (var i = 0u; i < I; i++) {
3982
- let iv = input_buf[inB + i];
4512
+ let iv = input_buf[inB + i]; // loaded ONCE, reused across 2 groups
3983
4513
  acc0 += weight_buf[wb0 + i] * iv;
3984
4514
  acc1 += weight_buf[wb1 + i] * iv;
3985
- acc2 += weight_buf[wb2 + i] * iv;
3986
- acc3 += weight_buf[wb3 + i] * iv;
3987
4515
  }
3988
4516
  }
3989
4517
  }
@@ -3991,10 +4519,156 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
3991
4519
  let baseO = y * params.out_w * O + x * O;
3992
4520
  output_buf[baseO + o0] = act(acc0, params.activation);
3993
4521
  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
4522
  }
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 c(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 O=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,d=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,n.outChannels),this.inputs=[e],this.weights=[t.upload(c(r.weights)),t.upload(c(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,d,l,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 ze=`// Depthwise Conv2d \u2014 groups = in_channels (each channel convolved independently).
4523
+ `;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 ve(a,t,e,r){return (a-1)*e-2*r+t}function br(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"?br(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?me(a[n]):a[n];return e}var O=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Le:Re;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=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,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 Ve=`// ConvTranspose2d \u2014 gather form, f32 variant. See conv_transpose2d_f16.wgsl for
4524
+ // the math; this is the f32 storage build (mat4x4<f32>).
4525
+
4526
+ struct Params {
4527
+ in_h : u32,
4528
+ in_w : u32,
4529
+ out_h : u32,
4530
+ out_w : u32,
4531
+ in_groups : u32,
4532
+ out_groups : u32,
4533
+ kernel_h : u32,
4534
+ kernel_w : u32,
4535
+ stride : u32,
4536
+ pad_top : u32,
4537
+ pad_left : u32,
4538
+ activation : u32,
4539
+ }
4540
+
4541
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
4542
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f32>>;
4543
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f32>>;
4544
+ @group(0) @binding(3) var<uniform> params : Params;
4545
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f32>>;
4546
+
4547
+ fn act(v: vec4<f32>, a: u32) -> vec4<f32> {
4548
+ if (a == 1u) { return clamp(v, vec4<f32>(0.0), vec4<f32>(6.0)); }
4549
+ if (a == 2u) { return max(v, vec4<f32>(0.0)); }
4550
+ if (a == 3u) { return max(v, 0.1 * v); }
4551
+ return v;
4552
+ }
4553
+
4554
+ @compute @workgroup_size(8, 8, 1)
4555
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4556
+ let ox = gid.x;
4557
+ let oy = gid.y;
4558
+ let o = gid.z;
4559
+
4560
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
4561
+ return;
4562
+ }
4563
+
4564
+ let I = params.in_groups;
4565
+ let O = params.out_groups;
4566
+ let s = i32(params.stride);
4567
+
4568
+ var result = bias_buf[o];
4569
+
4570
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
4571
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
4572
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
4573
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
4574
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
4575
+ continue;
4576
+ }
4577
+ let iy = iy_num / s;
4578
+ let ix = ix_num / s;
4579
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
4580
+ continue;
4581
+ }
4582
+
4583
+ let z = ky * params.kernel_w + kx;
4584
+ for (var i = 0u; i < I; i++) {
4585
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
4586
+ let w_idx = z * O * I + o * I + i;
4587
+ result += weight_buf[w_idx] * input_buf[in_idx];
4588
+ }
4589
+ }
4590
+ }
4591
+
4592
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
4593
+ }
4594
+ `;var Ne=`enable f16;
4595
+
4596
+ // ConvTranspose2d \u2014 gather form, full f16 variant.
4597
+ // Each output (oy,ox) sums every input pixel + kernel tap that maps onto it:
4598
+ // iy = (oy + pad - ky) / stride (must divide evenly and be in bounds)
4599
+ // No explicit kernel flip \u2014 the (oy + pad - ky) indexing carries it.
4600
+ // Weight layout is IDENTICAL to conv2d (mat4x4[z][o][i], M[in_sub][out_sub] =
4601
+ // W(in, out, ky, kx)), so the op uploads the flat buffer unchanged.
4602
+
4603
+ struct Params {
4604
+ in_h : u32,
4605
+ in_w : u32,
4606
+ out_h : u32,
4607
+ out_w : u32,
4608
+ in_groups : u32,
4609
+ out_groups : u32,
4610
+ kernel_h : u32,
4611
+ kernel_w : u32,
4612
+ stride : u32,
4613
+ pad_top : u32,
4614
+ pad_left : u32,
4615
+ activation : u32,
4616
+ }
4617
+
4618
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
4619
+ @group(0) @binding(1) var<storage, read> weight_buf : array<mat4x4<f16>>;
4620
+ @group(0) @binding(2) var<storage, read> bias_buf : array<vec4<f16>>;
4621
+ @group(0) @binding(3) var<uniform> params : Params;
4622
+ @group(0) @binding(4) var<storage, read_write> output_buf : array<vec4<f16>>;
4623
+
4624
+ fn act(v: vec4<f16>, a: u32) -> vec4<f16> {
4625
+ if (a == 1u) { return clamp(v, vec4<f16>(0.0h), vec4<f16>(6.0h)); }
4626
+ if (a == 2u) { return max(v, vec4<f16>(0.0h)); }
4627
+ if (a == 3u) { return max(v, 0.1h * v); }
4628
+ return v;
4629
+ }
4630
+
4631
+ @compute @workgroup_size(8, 8, 1)
4632
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4633
+ let ox = gid.x;
4634
+ let oy = gid.y;
4635
+ let o = gid.z;
4636
+
4637
+ if (ox >= params.out_w || oy >= params.out_h || o >= params.out_groups) {
4638
+ return;
4639
+ }
4640
+
4641
+ let I = params.in_groups;
4642
+ let O = params.out_groups;
4643
+ let s = i32(params.stride);
4644
+
4645
+ var result = bias_buf[o];
4646
+
4647
+ for (var ky = 0u; ky < params.kernel_h; ky++) {
4648
+ for (var kx = 0u; kx < params.kernel_w; kx++) {
4649
+ let iy_num = i32(oy) + i32(params.pad_top) - i32(ky);
4650
+ let ix_num = i32(ox) + i32(params.pad_left) - i32(kx);
4651
+ if (iy_num < 0 || ix_num < 0 || (iy_num % s) != 0 || (ix_num % s) != 0) {
4652
+ continue;
4653
+ }
4654
+ let iy = iy_num / s;
4655
+ let ix = ix_num / s;
4656
+ if (iy >= i32(params.in_h) || ix >= i32(params.in_w)) {
4657
+ continue;
4658
+ }
4659
+
4660
+ let z = ky * params.kernel_w + kx;
4661
+ for (var i = 0u; i < I; i++) {
4662
+ let in_idx = u32(iy) * params.in_w * I + u32(ix) * I + i;
4663
+ let w_idx = z * O * I + o * I + i;
4664
+ result += weight_buf[w_idx] * input_buf[in_idx];
4665
+ }
4666
+ }
4667
+ }
4668
+
4669
+ output_buf[oy * params.out_w * O + ox * O + o] = act(result, params.activation);
4670
+ }
4671
+ `;var M=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Ne:Ve;let i=ve(e.h,n.kernel,n.stride,n.padding),o=ve(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 $e=`// Depthwise Conv2d \u2014 groups = in_channels (each channel convolved independently).
3998
4672
  //
3999
4673
  // Weight layout: [K*K][channel_groups] array of vec4
4000
4674
  // weight index = (ky*kernel_w + kx) * channel_groups + c
@@ -4069,7 +4743,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4069
4743
  let out_idx = y * params.out_w * C + x * C + c;
4070
4744
  output_buf[out_idx] = result;
4071
4745
  }
4072
- `;var Me=`enable f16;
4746
+ `;var je=`enable f16;
4073
4747
 
4074
4748
  // Depthwise conv2d \u2014 full f16 variant. All buffers f16.
4075
4749
 
@@ -4134,7 +4808,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4134
4808
 
4135
4809
  output_buf[y * params.out_w * C + x * C + c] = result;
4136
4810
  }
4137
- `;var z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Me:ze;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),d=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(c(r.weights)),t.upload(c(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,d,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.
4811
+ `;var z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?je:$e;let i=_(e.h,n.kernel,n.stride,n.padding),o=_(e.w,n.kernel,n.stride,n.padding),s=e.c/4,u=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,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 qe=`// Element-wise add of two tensors \u2014 used for residual connections in MBConv blocks.
4138
4812
  // Operates on the flat float buffer directly; layout is irrelevant for a pure element-wise op.
4139
4813
 
4140
4814
  struct Params {
@@ -4155,7 +4829,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4155
4829
  if (idx >= params.size) { return; }
4156
4830
  output[idx] = input_a[idx] + input_b[idx];
4157
4831
  }
4158
- `;var Re=`enable f16;
4832
+ `;var Xe=`enable f16;
4159
4833
 
4160
4834
  // Element-wise add \u2014 full f16 variant.
4161
4835
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -4178,7 +4852,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4178
4852
  if (idx >= params.size) { return; }
4179
4853
  output[idx] = input_a[idx] + input_b[idx];
4180
4854
  }
4181
- `;var M=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)).
4855
+ `;var D=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?Xe:qe;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 Ke=`// Element-wise sigmoid: output = 1 / (1 + exp(-x)).
4182
4856
  // Operates on packed vec4 buffers (NHWC layout). exp() and arithmetic are element-wise on vec4.
4183
4857
 
4184
4858
  struct Params {
@@ -4198,7 +4872,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4198
4872
  if (idx >= params.n_groups) { return; }
4199
4873
  output_buf[idx] = 1.0 / (1.0 + exp(-input_buf[idx]));
4200
4874
  }
4201
- `;var Le=`enable f16;
4875
+ `;var Ye=`enable f16;
4202
4876
 
4203
4877
  // Sigmoid \u2014 full f16 variant.
4204
4878
 
@@ -4220,7 +4894,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4220
4894
  let x = vec4<f32>(input_buf[idx]);
4221
4895
  output_buf[idx] = vec4<f16>(1.0 / (1.0 + exp(-x)));
4222
4896
  }
4223
- `;var D=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.
4897
+ `;var H=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?Ye:Ke;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 Je=`// Element-wise tanh \u2014 used by ConvGRU candidate activation.
4224
4898
  // Operates on packed vec4 buffers (NHWC layout). tanh() is element-wise on vec4.
4225
4899
 
4226
4900
  struct Params {
@@ -4240,7 +4914,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4240
4914
  if (idx >= params.n_groups) { return; }
4241
4915
  output_buf[idx] = tanh(input_buf[idx]);
4242
4916
  }
4243
- `;var Ne=`enable f16;
4917
+ `;var Qe=`enable f16;
4244
4918
 
4245
4919
  // Tanh \u2014 full f16 variant.
4246
4920
 
@@ -4262,7 +4936,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4262
4936
  let x = vec4<f32>(input_buf[idx]);
4263
4937
  output_buf[idx] = vec4<f16>(tanh(x));
4264
4938
  }
4265
- `;var R=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.
4939
+ `;var R=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e){super(t),this.shader=t.dtype==="f16"?Qe:Je;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 Ze=`// Element-wise multiply \u2014 used in ConvGRU for r \u2299 h_prev.
4266
4940
  // Same flat-float layout as add.wgsl.
4267
4941
 
4268
4942
  struct Params {
@@ -4283,7 +4957,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4283
4957
  if (idx >= params.size) { return; }
4284
4958
  output[idx] = input_a[idx] * input_b[idx];
4285
4959
  }
4286
- `;var je=`enable f16;
4960
+ `;var et=`enable f16;
4287
4961
 
4288
4962
  // Element-wise multiply \u2014 full f16 variant.
4289
4963
  // array<f16> is binary-compatible with array<vec4<f16>> written by the f16 conv shaders.
@@ -4306,7 +4980,208 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4306
4980
  if (idx >= params.size) { return; }
4307
4981
  output[idx] = input_a[idx] * input_b[idx];
4308
4982
  }
4309
- `;var H=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).
4983
+ `;var L=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?et:Ze;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 tt=`// Bilinear gather-warp (f32). See warp_f16.wgsl for the math.
4984
+
4985
+ struct Params {
4986
+ h : u32,
4987
+ w : u32,
4988
+ flow_scale : f32,
4989
+ }
4990
+
4991
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f32>>;
4992
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f32>>;
4993
+ @group(0) @binding(2) var<uniform> params : Params;
4994
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f32>>;
4995
+
4996
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
4997
+ let cx = clamp(x, 0, W - 1);
4998
+ let cy = clamp(y, 0, H - 1);
4999
+ return source_buf[u32(cy) * u32(W) + u32(cx)];
5000
+ }
5001
+
5002
+ @compute @workgroup_size(8, 8, 1)
5003
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5004
+ let x = gid.x;
5005
+ let y = gid.y;
5006
+ if (x >= params.w || y >= params.h) { return; }
5007
+
5008
+ let W = i32(params.w);
5009
+ let H = i32(params.h);
5010
+ let idx = y * params.w + x;
5011
+
5012
+ let f = flow_buf[idx].xy;
5013
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
5014
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
5015
+
5016
+ let x0 = i32(floor(sx));
5017
+ let y0 = i32(floor(sy));
5018
+ let tx = sx - f32(x0);
5019
+ let ty = sy - f32(y0);
5020
+
5021
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
5022
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
5023
+ output_buf[idx] = mix(top, bot, ty);
5024
+ }
5025
+ `;var rt=`enable f16;
5026
+
5027
+ // Bilinear gather-warp (f16 storage, f32 coordinate math). For each output pixel
5028
+ // p, sample the source at p + flow_scale\xB7flow[p].xy and bilinearly interpolate,
5029
+ // clamping the sample to the edge (border-replicate). Source + flow are 4-ch
5030
+ // (1 group), same resolution; flow vector is in .xy.
5031
+
5032
+ struct Params {
5033
+ h : u32,
5034
+ w : u32,
5035
+ flow_scale : f32,
5036
+ }
5037
+
5038
+ @group(0) @binding(0) var<storage, read> source_buf : array<vec4<f16>>;
5039
+ @group(0) @binding(1) var<storage, read> flow_buf : array<vec4<f16>>;
5040
+ @group(0) @binding(2) var<uniform> params : Params;
5041
+ @group(0) @binding(3) var<storage, read_write> output_buf : array<vec4<f16>>;
5042
+
5043
+ fn samp(x: i32, y: i32, W: i32, H: i32) -> vec4<f32> {
5044
+ let cx = clamp(x, 0, W - 1);
5045
+ let cy = clamp(y, 0, H - 1);
5046
+ return vec4<f32>(source_buf[u32(cy) * u32(W) + u32(cx)]);
5047
+ }
5048
+
5049
+ @compute @workgroup_size(8, 8, 1)
5050
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5051
+ let x = gid.x;
5052
+ let y = gid.y;
5053
+ if (x >= params.w || y >= params.h) { return; }
5054
+
5055
+ let W = i32(params.w);
5056
+ let H = i32(params.h);
5057
+ let idx = y * params.w + x;
5058
+
5059
+ let f = vec2<f32>(flow_buf[idx].xy);
5060
+ let sx = clamp(f32(x) + params.flow_scale * f.x, 0.0, f32(W - 1));
5061
+ let sy = clamp(f32(y) + params.flow_scale * f.y, 0.0, f32(H - 1));
5062
+
5063
+ let x0 = i32(floor(sx));
5064
+ let y0 = i32(floor(sy));
5065
+ let tx = sx - f32(x0);
5066
+ let ty = sy - f32(y0);
5067
+
5068
+ let top = mix(samp(x0, y0, W, H), samp(x0 + 1, y0, W, H), tx);
5069
+ let bot = mix(samp(x0, y0 + 1, W, H), samp(x0 + 1, y0 + 1, W, H), tx);
5070
+ output_buf[idx] = vec4<f16>(mix(top, bot, ty));
5071
+ }
5072
+ `;var V=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?rt:tt,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 nt=`// Flow-gated temporal stabilizer (f32). See stabilize_f16.wgsl for the math.
5073
+
5074
+ struct Params {
5075
+ h : u32,
5076
+ w : u32,
5077
+ t_lo : f32,
5078
+ t_hi : f32,
5079
+ leak : f32,
5080
+ release : f32,
5081
+ t_div : f32,
5082
+ div_scale: f32,
5083
+ step_x : u32,
5084
+ step_y : u32,
5085
+ }
5086
+
5087
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f32>>;
5088
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f32>>;
5089
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f32>>;
5090
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f32>>;
5091
+ @group(0) @binding(4) var<uniform> params : Params;
5092
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f32>>;
5093
+
5094
+ @compute @workgroup_size(8, 8, 1)
5095
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5096
+ let x = gid.x;
5097
+ let y = gid.y;
5098
+ if (x >= params.w || y >= params.h) { return; }
5099
+ let idx = y * params.w + x;
5100
+
5101
+ let mag = length(flow_buf[idx].xy);
5102
+ let env_prev = env_prev_buf[idx].y;
5103
+ let env = max(mag, params.release * env_prev);
5104
+
5105
+ let xr = min(x + params.step_x, params.w - 1u);
5106
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
5107
+ let yd = min(y + params.step_y, params.h - 1u);
5108
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
5109
+ let dfx = flow_buf[y * params.w + xr].x - flow_buf[y * params.w + xl].x;
5110
+ let dfy = flow_buf[yd * params.w + x].y - flow_buf[yu * params.w + x].y;
5111
+ let divg = abs(dfx + dfy);
5112
+
5113
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
5114
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
5115
+ let g = max(max(g_mag, g_div), params.leak);
5116
+
5117
+ let pred = pred_buf[idx].x;
5118
+ let refv = ref_buf[idx].x;
5119
+ let stab = g * pred + (1.0 - g) * refv;
5120
+
5121
+ output_buf[idx] = vec4<f32>(stab, env, 0.0, 0.0);
5122
+ }
5123
+ `;var at=`enable f16;
5124
+
5125
+ // Flow-gated temporal stabilizer (f16 storage, f32 gate math). Per pixel:
5126
+ // env = max(|flow.xy|, release\xB7envPrev.y) peak-hold (fast attack, slow release)
5127
+ // div = |\u2202fx/\u2202x + \u2202fy/\u2202y| flow divergence (occlusion seam)
5128
+ // g = max(clamp((env-tLo)/(tHi-tLo),0,1), clamp((div-tDiv)/divScale,0,1), leak)
5129
+ // out = vec4((g\xB7pred + (1-g)\xB7ref).x, env, 0, 0)
5130
+ // The divergence term opens the gate at occlusion/disocclusion boundaries (where
5131
+ // the flow tears but the revealed-background magnitude is ~0). Finite-difference
5132
+ // step spans ~1 base/4 pixel. alpha is in .x of pred/ref; env threads via .y.
5133
+
5134
+ struct Params {
5135
+ h : u32,
5136
+ w : u32,
5137
+ t_lo : f32,
5138
+ t_hi : f32,
5139
+ leak : f32,
5140
+ release : f32,
5141
+ t_div : f32,
5142
+ div_scale: f32,
5143
+ step_x : u32,
5144
+ step_y : u32,
5145
+ }
5146
+
5147
+ @group(0) @binding(0) var<storage, read> flow_buf : array<vec4<f16>>;
5148
+ @group(0) @binding(1) var<storage, read> pred_buf : array<vec4<f16>>;
5149
+ @group(0) @binding(2) var<storage, read> ref_buf : array<vec4<f16>>;
5150
+ @group(0) @binding(3) var<storage, read> env_prev_buf : array<vec4<f16>>;
5151
+ @group(0) @binding(4) var<uniform> params : Params;
5152
+ @group(0) @binding(5) var<storage, read_write> output_buf : array<vec4<f16>>;
5153
+
5154
+ @compute @workgroup_size(8, 8, 1)
5155
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5156
+ let x = gid.x;
5157
+ let y = gid.y;
5158
+ if (x >= params.w || y >= params.h) { return; }
5159
+ let idx = y * params.w + x;
5160
+
5161
+ let mag = length(vec2<f32>(flow_buf[idx].xy));
5162
+ let env_prev = f32(env_prev_buf[idx].y);
5163
+ let env = max(mag, params.release * env_prev);
5164
+
5165
+ // Flow divergence over a \xB1step finite-difference (clamped to the edges).
5166
+ let xr = min(x + params.step_x, params.w - 1u);
5167
+ let xl = select(x - params.step_x, 0u, x < params.step_x);
5168
+ let yd = min(y + params.step_y, params.h - 1u);
5169
+ let yu = select(y - params.step_y, 0u, y < params.step_y);
5170
+ let dfx = f32(flow_buf[y * params.w + xr].x) - f32(flow_buf[y * params.w + xl].x);
5171
+ let dfy = f32(flow_buf[yd * params.w + x].y) - f32(flow_buf[yu * params.w + x].y);
5172
+ let divg = abs(dfx + dfy);
5173
+
5174
+ let g_mag = clamp((env - params.t_lo) / max(params.t_hi - params.t_lo, 1e-3), 0.0, 1.0);
5175
+ let g_div = clamp((divg - params.t_div) / max(params.div_scale, 1e-3), 0.0, 1.0);
5176
+ let g = max(max(g_mag, g_div), params.leak);
5177
+
5178
+ let pred = f32(pred_buf[idx].x);
5179
+ let refv = f32(ref_buf[idx].x);
5180
+ let stab = g * pred + (1.0 - g) * refv;
5181
+
5182
+ output_buf[idx] = vec4<f16>(f16(stab), f16(env), 0.0h, 0.0h);
5183
+ }
5184
+ `;var N=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n,i,o){super(t),this.shader=t.dtype==="f16"?at:nt,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 it=`// Bilinear upsample (arbitrary ratio), align_corners=False (matches PyTorch default).
4310
5185
  // Input/output in NHWC vec4 format: index = y*W*(C/4) + x*(C/4) + c_group.
4311
5186
  // Each thread computes one output pixel for one channel group (vec4 = 4 channels).
4312
5187
 
@@ -4364,7 +5239,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4364
5239
 
4365
5240
  output_buf[oy * params.out_w * C + ox * C + c] = result;
4366
5241
  }
4367
- `;var Xe=`enable f16;
5242
+ `;var ot=`enable f16;
4368
5243
 
4369
5244
  // Bilinear upsample 2\xD7 \u2014 full f16 variant.
4370
5245
  // Interpolation weights (wx, wy) and intermediate blends computed in f32 for
@@ -4420,7 +5295,53 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4420
5295
 
4421
5296
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(result);
4422
5297
  }
4423
- `;var L=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
5298
+ `;var $=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?ot:it;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 st=`// Top-left crop (f32). See crop_f16.wgsl.
5299
+
5300
+ struct Params {
5301
+ in_w : u32,
5302
+ out_h : u32,
5303
+ out_w : u32,
5304
+ groups : u32,
5305
+ }
5306
+
5307
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f32>>;
5308
+ @group(0) @binding(1) var<uniform> params : Params;
5309
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f32>>;
5310
+
5311
+ @compute @workgroup_size(8, 8, 1)
5312
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5313
+ let x = gid.x;
5314
+ let y = gid.y;
5315
+ let g = gid.z;
5316
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
5317
+ let G = params.groups;
5318
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
5319
+ }
5320
+ `;var ut=`enable f16;
5321
+
5322
+ // Top-left crop: output[y,x,g] = input[y,x,g] for y<outH, x<outW (training crop_like).
5323
+
5324
+ struct Params {
5325
+ in_w : u32,
5326
+ out_h : u32,
5327
+ out_w : u32,
5328
+ groups : u32,
5329
+ }
5330
+
5331
+ @group(0) @binding(0) var<storage, read> input_buf : array<vec4<f16>>;
5332
+ @group(0) @binding(1) var<uniform> params : Params;
5333
+ @group(0) @binding(2) var<storage, read_write> output_buf : array<vec4<f16>>;
5334
+
5335
+ @compute @workgroup_size(8, 8, 1)
5336
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5337
+ let x = gid.x;
5338
+ let y = gid.y;
5339
+ let g = gid.z;
5340
+ if (x >= params.out_w || y >= params.out_h || g >= params.groups) { return; }
5341
+ let G = params.groups;
5342
+ output_buf[y * params.out_w * G + x * G + g] = input_buf[y * params.in_w * G + x * G + g];
5343
+ }
5344
+ `;var j=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?ut:st;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 pt=`// Bicubic upsample (arbitrary scale) \u2014 Keys cubic, a=-0.75 (PyTorch default
4424
5345
  // for mode='bicubic', align_corners=False). Direct 2D, 4\xD74 = 16 taps per
4425
5346
  // output pixel. NHWC vec4 layout: index = y*W*(C/4) + x*(C/4) + c_group.
4426
5347
 
@@ -4487,7 +5408,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4487
5408
 
4488
5409
  output_buf[oy * params.out_w * C + ox * C + c] = acc;
4489
5410
  }
4490
- `;var Ye=`enable f16;
5411
+ `;var lt=`enable f16;
4491
5412
 
4492
5413
  // Bicubic upsample \u2014 full f16 storage variant. Bicubic weights and the per-
4493
5414
  // pixel accumulator are computed in f32 (cheap to keep precision around the
@@ -4556,7 +5477,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4556
5477
 
4557
5478
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(acc);
4558
5479
  }
4559
- `;var V=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).
5480
+ `;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(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 ct=`// Channel concatenation: output = cat(A, B, dim=channel).
4560
5481
  // Both A and B must share the same H\xD7W and be in NHWC vec4 format.
4561
5482
  // Output layout: for each (y, x), the first a_groups vec4s come from A,
4562
5483
  // followed by b_groups vec4s from B.
@@ -4601,7 +5522,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4601
5522
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
4602
5523
  }
4603
5524
  }
4604
- `;var Je=`enable f16;
5525
+ `;var dt=`enable f16;
4605
5526
 
4606
5527
  // Channel concatenation \u2014 full f16 variant.
4607
5528
 
@@ -4642,7 +5563,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4642
5563
  output_buf[out_idx] = input_b[y * W * Bg + x * Bg + c_b];
4643
5564
  }
4644
5565
  }
4645
- `;var N=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.
5566
+ `;var X=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?dt:ct;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 ft=`// Conv2d + skip add fused.
4646
5567
  // Identical to conv2d.wgsl except skip is an activation input (binding 1),
4647
5568
  // added element-wise to the conv result at write time.
4648
5569
  // Eliminates the separate add dispatch and its intermediate buffer round-trip.
@@ -4716,7 +5637,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4716
5637
  let out_idx = y * params.out_w * O + x * O + o;
4717
5638
  output_buf[out_idx] = result + skip_buf[out_idx];
4718
5639
  }
4719
- `;var et=`enable f16;
5640
+ `;var ht=`enable f16;
4720
5641
 
4721
5642
  // Conv2d + skip add fused \u2014 full f16 variant.
4722
5643
 
@@ -4790,7 +5711,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4790
5711
  let out_idx = y * params.out_w * O + x * O + o;
4791
5712
  output_buf[out_idx] = result + skip_buf[out_idx];
4792
5713
  }
4793
- `;var $=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,d=i.outChannels/4,l=m(i.padding,e.h,o,i.kernel,i.stride),f=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(c(n.weights)),t.upload(c(n.bias))],this.createUniform("params","Params"),this.setUniform("params",new Uint32Array([e.h,e.w,o,u,s,d,i.kernel,i.kernel,i.stride,l,f,i.activation==="relu6"?1:0])),this.defaultSetup(),this.dispatch=[Math.ceil(u/8),Math.ceil(o/8),d];}};var tt=`// proj_residual: bespoke 1\xD71 conv (no activation) + residual add, fused.
5714
+ `;var K=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?ht:ft;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=m(i.padding,e.h,o,i.kernel,i.stride),f=m(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 gt=`// proj_residual: bespoke 1\xD71 conv (no activation) + residual add, fused.
4794
5715
  // Specializes conv2d_add to kernel=1 / stride=1 / pad=0 / no activation: drops
4795
5716
  // the kernel loop, the padding checks, and the activation branch. Used by the
4796
5717
  // MBConv project+residual tail. Both inputs share the same spatial resolution.
@@ -4835,7 +5756,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4835
5756
 
4836
5757
  output_buf[pix * O + o] = result;
4837
5758
  }
4838
- `;var rt=`enable f16;
5759
+ `;var _t=`enable f16;
4839
5760
 
4840
5761
  // proj_residual \u2014 full f16 variant. See proj_residual.wgsl for layout details.
4841
5762
  // Bespoke 1\xD71 conv (no activation) + residual add, fused.
@@ -4877,7 +5798,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4877
5798
 
4878
5799
  output_buf[pix * O + o] = result;
4879
5800
  }
4880
- `;var j=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(c(n.weights)),t.upload(c(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
5801
+ `;var Y=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?_t:gt;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 mt=`// concat_conv2d: fuses [concat(a, b) \u2192 conv 3\xD73 (pad 1) \u2192 relu6] into one
4881
5802
  // dispatch. Both inputs are already at the output resolution (the upstream
4882
5803
  // upsample stays a separate dispatch writing a clean intermediate, so the conv
4883
5804
  // reads are plain-indexed). Identical math to conv2d; the only difference is
@@ -4937,7 +5858,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4937
5858
  result = clamp(result, vec4<f32>(0.0), vec4<f32>(6.0));
4938
5859
  output_buf[(y * p.w + x) * O + o] = result;
4939
5860
  }
4940
- `;var at=`enable f16;
5861
+ `;var bt=`enable f16;
4941
5862
 
4942
5863
  // concat_conv2d \u2014 full f16 variant. See concat_conv2d.wgsl for layout details.
4943
5864
  // Fuses [concat(a, b) \u2192 conv 3\xD73 (pad 1) \u2192 relu6] into one dispatch.
@@ -4992,7 +5913,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4992
5913
  result = clamp(result, vec4<f16>(0.0h), vec4<f16>(6.0h));
4993
5914
  output_buf[(y * p.w + x) * O + o] = result;
4994
5915
  }
4995
- `;var q=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(c(n.weights)),t.upload(c(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.
5916
+ `;var J=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?bt:mt;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 vt=`// gates_fused: ConvGRU z + r gates, fused into one dispatch.
4996
5917
  // Production config (c_up=2, split_ratio=0.5 \u2192 passthrough=1, recurrent=1):
4997
5918
  // u_in : c_up=2 packed in a vec4 (.x = passthrough a, .y = recurrent b)
4998
5919
  // h_prev : hidden carrier \u2014 recurrent state in .z (see cand_update_fused: the
@@ -5037,7 +5958,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5037
5958
  let r = 1.0 / (1.0 + exp(-r_pre));
5038
5959
  output_buf[y * params.w + x] = vec4<f32>(z, r, 0.0, 0.0);
5039
5960
  }
5040
- `;var ot=`enable f16;
5961
+ `;var xt=`enable f16;
5041
5962
 
5042
5963
  // gates_fused \u2014 full f16 variant. See gates_fused.wgsl for layout details.
5043
5964
  // ConvGRU z + r gates (production config c_up=2, recurrent=1).
@@ -5079,7 +6000,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5079
6000
  let r = 1.0h / (1.0h + exp(-r_pre));
5080
6001
  output_buf[y * params.w + x] = vec4<f16>(z, r, 0.0h, 0.0h);
5081
6002
  }
5082
- `;var X=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(c(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.
6003
+ `;var Q=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?xt:vt,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 wt=`// cand_update_fused: ConvGRU candidate path + state update + output, fused.
5083
6004
  // Production config (c_up=2, recurrent=1):
5084
6005
  // u_in : c_up=2 (.x = a passthrough, .y = b recurrent)
5085
6006
  // h_prev : hidden carrier \u2014 recurrent state in .z (the previous frame's
@@ -5132,7 +6053,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5132
6053
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
5133
6054
  output_buf[cur] = vec4<f32>(u_cur.x, b_out, h_new, 0.0);
5134
6055
  }
5135
- `;var st=`enable f16;
6056
+ `;var yt=`enable f16;
5136
6057
 
5137
6058
  // cand_update_fused \u2014 full f16 variant. See cand_update_fused.wgsl for details.
5138
6059
  // ConvGRU candidate + state update + output (production config c_up=2, recurrent=1).
@@ -5178,7 +6099,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5178
6099
  let b_out = u_cur.y + gamma_buf[0].x * h_new;
5179
6100
  output_buf[cur] = vec4<f16>(u_cur.x, b_out, h_new, 0.0h);
5180
6101
  }
5181
- `;var K=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(c(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).
6102
+ `;var Z=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i,o){super(t),this.shader=t.dtype==="f16"?yt:wt,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 kt=`// conv_expand: bespoke N\u21922 conv 3\xD73 (pad 1) + relu (wrapper expand_feat).
5182
6103
  // Expands feat_lr (in_c, mult of 4) to the c_up=2 carrier \u2014 output .xy = the 2
5183
6104
  // native channels, .zw = 0. mat4x2 per (kpos, in_group) with a vec2 accumulator.
5184
6105
  // Weight: 9 * in_groups mat4x2 (8 floats each, col-major). Bias .xy.
@@ -5215,7 +6136,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5215
6136
  result = max(result, vec2<f32>(0.0)); // expand_feat is F.relu
5216
6137
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
5217
6138
  }
5218
- `;var lt=`enable f16;
6139
+ `;var Ct=`enable f16;
5219
6140
 
5220
6141
  // conv_expand \u2014 full f16 variant. See conv_expand.wgsl for layout details.
5221
6142
  // Bespoke N\u21922 conv 3\xD73 (pad 1) + relu (wrapper expand_feat).
@@ -5252,7 +6173,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5252
6173
  result = max(result, vec2<f16>(0.0h));
5253
6174
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
5254
6175
  }
5255
- `;var Y=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(c(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).
6176
+ `;var ee=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(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 Pt=`// cat_conv_6to2: fused concat(u, d) + 6\u21922 conv 3\xD73 (pad 1) + relu (E up1_combine).
5256
6177
  // u = c_up=2 carrier (.xy); d = c_high=4 (full vec4). Both same resolution.
5257
6178
  // Channel order concat([u, d]) = (u.x, u.y, d.x, d.y, d.z, d.w), split into
5258
6179
  // v3a = (u.x, u.y, d.x) v3b = d.yzw
@@ -5292,7 +6213,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5292
6213
  result = max(result, vec2<f32>(0.0)); // up1_combine is F.relu
5293
6214
  output_buf[y * params.w + x] = vec4<f32>(result, 0.0, 0.0);
5294
6215
  }
5295
- `;var dt=`enable f16;
6216
+ `;var Tt=`enable f16;
5296
6217
 
5297
6218
  // cat_conv_6to2 \u2014 full f16 variant. See cat_conv_6to2.wgsl for layout details.
5298
6219
  // Fused concat(u, d) + 6\u21922 conv 3\xD73 (pad 1) + relu (E up1_combine).
@@ -5331,7 +6252,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5331
6252
  result = max(result, vec2<f16>(0.0h));
5332
6253
  output_buf[y * params.w + x] = vec4<f16>(result, 0.0h, 0.0h);
5333
6254
  }
5334
- `;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,4),this.inputs=[e,r],this.weights=[t.upload(c(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 ft=`// down_adapter: fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no
6255
+ `;var te=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Tt:Pt,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=`// down_adapter: fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no
5335
6256
  // act) into one dispatch. E variant: down2 (c_high=4 \u2192 c_low=4, stride 2) +
5336
6257
  // adapter. A/B variant: down1 (RGB .xyz \u2192 4, stride 2/3) + adapter (the down
5337
6258
  // weight's 4th input column is zeroed at export for RGB input). Symmetric pad.
@@ -5379,7 +6300,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5379
6300
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
5380
6301
  output_buf[y * p.out_w + x] = vec4<f32>(adapt_out.xyz, 0.0);
5381
6302
  }
5382
- `;var ht=`enable f16;
6303
+ `;var Wt=`enable f16;
5383
6304
 
5384
6305
  // down_adapter \u2014 full f16 variant. See down_adapter.wgsl for layout details.
5385
6306
  // Fused stride-N 3\xD73 conv (4\u21924) + relu + 1\xD71 adapter (4\u21923, no act).
@@ -5424,7 +6345,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5424
6345
  let adapt_out = adapt_w[0] * down_out + adapt_b[0];
5425
6346
  output_buf[y * p.out_w + x] = vec4<f16>(adapt_out.xyz, 0.0h);
5426
6347
  }
5427
- `;var J=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?ht:ft;let o=_(e.h,3,i.stride,1),u=_(e.w,3,i.stride,1),s=m(1,e.h,o,3,i.stride),d=m(1,e.w,u,3,i.stride);this.output=t.tensor(o,u,4),this.inputs=[e],this.weights=[t.upload(c(r.weights)),t.upload(g(r.bias)),t.upload(c(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,d,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).
6348
+ `;var re=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.h,3,i.stride,1),s=_(e.w,3,i.stride,1),u=m(1,e.h,o,3,i.stride),l=m(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 It=`// up_final: fused concat(u, rgb) \u2192 conv 3\xD73 5\u21921 \u2192 sigmoid (A/B alpha head).
5428
6349
  // u = c_up=2 carrier (.xy); rgb = x_hr (.xyz). 5 inputs \u2192 1 alpha (output .x).
5429
6350
  // Weight: 18 vec4 \u2014 [0..8] = (w0, w1, 0, 0) for u per kpos; [9..17] =
5430
6351
  // (w2, w3, w4, 0) for rgb per kpos. Bias .x.
@@ -5458,7 +6379,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5458
6379
 
5459
6380
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
5460
6381
  }
5461
- `;var _t=`enable f16;
6382
+ `;var Bt=`enable f16;
5462
6383
 
5463
6384
  // up_final \u2014 full f16 variant. See up_final.wgsl for layout details.
5464
6385
  // Fused concat(u, rgb) \u2192 conv 3\xD73 5\u21921 \u2192 sigmoid (A/B alpha head).
@@ -5492,7 +6413,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5492
6413
 
5493
6414
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
5494
6415
  }
5495
- `;var Z=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(c(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
6416
+ `;var ne=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=`// up_final_skip: C/D alpha head. Fused concat(u, d_full, rgb) \u2192 conv 3\xD73 9\u21921
5496
6417
  // \u2192 sigmoid. u = c_up=2 (.xy); d_full = c_high=4 full-res skip (full vec4);
5497
6418
  // rgb = x_hr (.xyz). Channel order concat = 2 + 4 + 3 = 9. Output .x = alpha.
5498
6419
  // Weight: 27 vec4 (3 per kpos): [kpos*3+0]=(w0,w1,0,0) u; [kpos*3+1]=(w2..w5)
@@ -5529,7 +6450,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5529
6450
 
5530
6451
  output_buf[y * params.w + x] = vec4<f32>(1.0 / (1.0 + exp(-acc)), 0.0, 0.0, 0.0);
5531
6452
  }
5532
- `;var bt=`enable f16;
6453
+ `;var Gt=`enable f16;
5533
6454
 
5534
6455
  // up_final_skip \u2014 full f16 variant. See up_final_skip.wgsl for layout details.
5535
6456
  // C/D alpha head: fused concat(u, d_full, rgb) \u2192 conv 3\xD73 9\u21921 \u2192 sigmoid.
@@ -5565,7 +6486,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5565
6486
 
5566
6487
  output_buf[y * params.w + x] = vec4<f16>(1.0h / (1.0h + exp(-acc)), 0.0h, 0.0h, 0.0h);
5567
6488
  }
5568
- `;var ee=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(c(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.
6489
+ `;var ae=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n,i){super(t),this.shader=t.dtype==="f16"?Gt: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))],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 Ft=`// Bilinear upsample + channel concat fused.
5569
6490
  // input_a is the decoder tensor at small spatial resolution (in_h \xD7 in_w).
5570
6491
  // input_b is the encoder skip feature already at output resolution (out_h \xD7 out_w).
5571
6492
  // For output channels 0..a_groups-1: bilinearly interpolate from input_a.
@@ -5626,7 +6547,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5626
6547
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
5627
6548
  }
5628
6549
  }
5629
- `;var xt=`enable f16;
6550
+ `;var Et=`enable f16;
5630
6551
 
5631
6552
  // Bilinear upsample + channel concat fused \u2014 full f16 variant.
5632
6553
  // Bilinear weights (wx, wy) and intermediate blends computed in f32; result cast to f16.
@@ -5686,7 +6607,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5686
6607
  output_buf[out_idx] = input_b[oy * params.out_w * params.b_groups + ox * params.b_groups + c_b];
5687
6608
  }
5688
6609
  }
5689
- `;var te=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.
6610
+ `;var ie=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Et:Ft;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 At=`// Bilinear upsample + 1\xD71 pointwise conv fused.
5690
6611
  // For each output pixel, bilinearly samples the small input for each in_group,
5691
6612
  // immediately applies the 1\xD71 conv weights, and writes the activated result.
5692
6613
  // Eliminates the intermediate full-resolution upsample buffer.
@@ -5753,7 +6674,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5753
6674
 
5754
6675
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
5755
6676
  }
5756
- `;var yt=`enable f16;
6677
+ `;var Ot=`enable f16;
5757
6678
 
5758
6679
  // Bilinear upsample + 1\xD71 pointwise conv fused \u2014 full f16 variant.
5759
6680
  // Bilinear weights and intermediate blends computed in f32; conv accumulation in f16.
@@ -5820,7 +6741,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5820
6741
 
5821
6742
  output_buf[oy * params.out_w * params.out_groups + ox * params.out_groups + og] = result;
5822
6743
  }
5823
- `;var re=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(c(r.weights)),t.upload(c(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.
6744
+ `;var oe=class extends p{inputs;weights;output;dispatch;shader;constructor(t,e,r,n){super(t),this.shader=t.dtype==="f16"?Ot:At;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 Mt=`// Bilinear upsample + sigmoid fused.
5824
6745
  // Identical to bilinear_upsample.wgsl except sigmoid is applied at write time.
5825
6746
  // Eliminates the intermediate full-resolution buffer and the separate sigmoid dispatch.
5826
6747
 
@@ -5874,7 +6795,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5874
6795
 
5875
6796
  output_buf[oy * params.out_w * C + ox * C + c] = 1.0 / (1.0 + exp(-result));
5876
6797
  }
5877
- `;var Ct=`enable f16;
6798
+ `;var zt=`enable f16;
5878
6799
 
5879
6800
  // Bilinear upsample + sigmoid fused \u2014 full f16 variant.
5880
6801
  // Interpolation computed in f32 for accuracy; sigmoid and result cast to f16.
@@ -5929,7 +6850,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
5929
6850
 
5930
6851
  output_buf[oy * params.out_w * C + ox * C + c] = vec4<f16>(1.0 / (1.0 + exp(-result)));
5931
6852
  }
5932
- `;var ne=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.
6853
+ `;var se=class extends p{inputs;weights=[];output;dispatch;shader;constructor(t,e,r){super(t),this.shader=t.dtype==="f16"?zt:Mt;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 Dt=`// Composite an RGBA image over a solid background, gated by a 1-ch alpha.
5933
6854
  // Fragment writes the canvas's swapchain texture (premultiplied output).
5934
6855
  //
5935
6856
  // Caller invariants (matched in CompositeSolidWebGPU):
@@ -5974,7 +6895,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
5974
6895
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
5975
6896
  return vec4<f32>(rgb, 1.0);
5976
6897
  }
5977
- `;var Tt=`enable f16;
6898
+ `;var Ht=`enable f16;
5978
6899
 
5979
6900
  // Composite an RGBA image over a solid background, gated by a 1-ch alpha.
5980
6901
  // f16 variant: image and alpha are stored as f16; values promote to f32 on
@@ -6023,7 +6944,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6023
6944
  let rgb = fg * a + params.bgColor.rgb * (1.0 - a);
6024
6945
  return vec4<f32>(rgb, 1.0);
6025
6946
  }
6026
- `;var ae=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
6947
+ `;var ue=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"?Ht:Dt,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 Rt=`// Like composite_solid but bg is an NHWC vec4 storage buffer (e.g. virtual
6027
6948
  // background image, or a blurred copy of the input).
6028
6949
 
6029
6950
  struct VertexOut {
@@ -6065,7 +6986,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6065
6986
  let rgb = fg * a + bgc * (1.0 - a);
6066
6987
  return vec4<f32>(rgb, 1.0);
6067
6988
  }
6068
- `;var It=`enable f16;
6989
+ `;var Lt=`enable f16;
6069
6990
 
6070
6991
  // Like composite_solid_f16 but bg is an NHWC vec4<f16> storage buffer (e.g. a
6071
6992
  // virtual background image, or a blurred copy of the input).
@@ -6109,7 +7030,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6109
7030
  let rgb = fg * a + bgc * (1.0 - a);
6110
7031
  return vec4<f32>(rgb, 1.0);
6111
7032
  }
6112
- `;var ie=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
7033
+ `;var pe=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"?Lt:Rt,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 Vt=`// Like composite_image but bg is sampled bilinearly \u2014 bg may be smaller than
6113
7034
  // (image, alpha). Used by CompositorBlur to skip the final full-res upsample
6114
7035
  // in the blur pyramid and let this shader's own per-pixel scan do the
6115
7036
  // expansion (the work is already happening here for the composite anyway).
@@ -6174,7 +7095,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6174
7095
  let rgb = fg * a + bgc * (1.0 - a);
6175
7096
  return vec4<f32>(rgb, 1.0);
6176
7097
  }
6177
- `;var Wt=`enable f16;
7098
+ `;var Nt=`enable f16;
6178
7099
 
6179
7100
  // f16 storage variant of composite_image_bilinear. bg is at a smaller
6180
7101
  // resolution and is bilinearly sampled to match (image, alpha) at full res.
@@ -6235,7 +7156,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6235
7156
  let rgb = fg * a + bgc * (1.0 - a);
6236
7157
  return vec4<f32>(rgb, 1.0);
6237
7158
  }
6238
- `;var oe=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,d=i.createShaderModule({code:s});this.pipeline=i.createRenderPipeline({layout:"auto",vertex:{module:d,entryPoint:"vs"},fragment:{module:d,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
7159
+ `;var le=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"?Nt:Vt,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 $t=`// Passthrough "compositor" \u2014 writes the image directly to the canvas
6239
7160
  // swapchain texture with no alpha math and no background. Used by RenderOp
6240
7161
  // when the renderer is in disabled state, so the output canvas reflects
6241
7162
  // the unmodified input frame instead of a stale matted result.
@@ -6273,7 +7194,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6273
7194
  let i = y * params.width + x;
6274
7195
  return vec4<f32>(image[i].rgb, 1.0);
6275
7196
  }
6276
- `;var Gt=`enable f16;
7197
+ `;var jt=`enable f16;
6277
7198
 
6278
7199
  // Passthrough "compositor" \u2014 f16 variant. Image is stored as f16; values
6279
7200
  // promote to f32 on read and the fragment writes f32 to the canvas
@@ -6309,7 +7230,7 @@ fn fs(in: VertexOut) -> @location(0) vec4<f32> {
6309
7230
  let i = y * params.width + x;
6310
7231
  return vec4<f32>(vec3<f32>(image[i].rgb), 1.0);
6311
7232
  }
6312
- `;var ue=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
7233
+ `;var ce=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"?jt:$t,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 qt=`// Input op \u2014 sample a regular 2D source texture (RGBA8 unorm) into the NHWC
6313
7234
  // vec4<f32> output buffer at the target resolution. Used for ImageBitmap
6314
7235
  // sources, which are uploaded into a persistent staging texture via
6315
7236
  // copyExternalImageToTexture before each dispatch.
@@ -6339,7 +7260,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6339
7260
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
6340
7261
  output_buf[y * params.out_w + x] = rgba;
6341
7262
  }
6342
- `;var Ft=`enable f16;
7263
+ `;var Xt=`enable f16;
6343
7264
 
6344
7265
  // Input op \u2014 f16 storage variant. Source is sampled as vec4<f32>; only the
6345
7266
  // store is demoted to vec4<f16>.
@@ -6369,7 +7290,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6369
7290
  let rgba = textureSampleLevel(src_tex, src_sampler, uv, 0.0);
6370
7291
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
6371
7292
  }
6372
- `;var At=`// Input op \u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
7293
+ `;var Kt=`// Input op \u2014 sample a GPUExternalTexture (zero-copy VideoFrame import) into
6373
7294
  // the NHWC vec4<f32> output buffer at the target resolution. Used when the
6374
7295
  // caller passes a VideoFrame to setSource(); requires importExternalTexture
6375
7296
  // to be called in the same task as the dispatch (the texture is invalidated
@@ -6400,7 +7321,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6400
7321
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
6401
7322
  output_buf[y * params.out_w + x] = rgba;
6402
7323
  }
6403
- `;var Ot=`enable f16;
7324
+ `;var Yt=`enable f16;
6404
7325
 
6405
7326
  // Input op \u2014 texture_external + f16 storage. Sample in f32, store as f16.
6406
7327
 
@@ -6429,4 +7350,4 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
6429
7350
  let rgba = textureSampleBaseClampToEdge(src_tex, src_sampler, uv);
6430
7351
  output_buf[y * params.out_w + x] = vec4<f16>(rgba);
6431
7352
  }
6432
- `;var un=a=>typeof VideoFrame<"u"&&a instanceof VideoFrame,se=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.canvasContext=n,this.canvasFormat=navigator.gpu.getPreferredCanvasFormat(),this.canvasContext.configure({device:t,format:this.canvasFormat,alphaMode:"premultiplied"}),this.ops={Conv2d:(i,o,u)=>new O(this,i,o,u),DepthwiseConv2d:(i,o,u)=>new z(this,i,o,u),Add:(i,o)=>new M(this,i,o),Sigmoid:i=>new D(this,i),Tanh:i=>new R(this,i),ElementwiseMul:(i,o)=>new H(this,i,o),BilinearUpsample:(i,o)=>new L(this,i,o),BicubicUpsample:(i,o)=>new V(this,i,o),ChannelConcat:(i,o)=>new N(this,i,o),Conv2dAdd:(i,o,u,s)=>new $(this,i,o,u,s),ProjResidual:(i,o,u,s)=>new j(this,i,o,u,s),ConcatConv2d:(i,o,u,s)=>new q(this,i,o,u,s),GatesFused:(i,o,u)=>new X(this,i,o,u),CandUpdateFused:(i,o,u,s,d)=>new K(this,i,o,u,s,d),ConvExpand:(i,o)=>new Y(this,i,o),CatConv6to2:(i,o,u)=>new Q(this,i,o,u),DownAdapter:(i,o,u,s)=>new J(this,i,o,u,s),UpFinal:(i,o,u)=>new Z(this,i,o,u),UpFinalSkip:(i,o,u,s)=>new ee(this,i,o,u,s),UpsampleConcat:(i,o,u)=>new te(this,i,o,u),UpsampleConv1x1:(i,o,u)=>new re(this,i,o,u),UpsampleSigmoid:(i,o)=>new ne(this,i,o),Input:(i,o)=>new se(this,i,o)},this.presenters={CompositeSolid:(i,o,u)=>{let s=new ae(this,i,o,u);return {run:()=>{s.setOutput(this.getCurrentDisplayTexture()),s.run();}}},CompositeImage:(i,o,u)=>{let s=new ie(this,i,o,u);return {run:()=>{s.setOutput(this.getCurrentDisplayTexture()),s.run();}}},CompositeImageBilinear:(i,o,u)=>{let s=new oe(this,i,o,u);return {run:()=>{s.setOutput(this.getCurrentDisplayTexture()),s.run();}}},CompositePassthrough:i=>{let o=new ue(this,i);return {run:()=>{o.setOutput(this.getCurrentDisplayTexture()),o.run();}}}};}device;canvas;dtype;ops;presenters;canvasContext;canvasFormat;bytesPerElement;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(){return this.canvasContext.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{he as EffectsPipeline,_e as WebGPUBackend};
7353
+ `;var Wn=a=>typeof VideoFrame<"u"&&a instanceof VideoFrame,de=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"?Xt:qt);}setSource(t){this.source=t;}run(){if(!this.source)throw new Error("InputWebGPU.run() called before setSource()");Wn(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"?Yt:Kt));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 In=navigator.gpu?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST:0,xe=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 O(this,i,o,s),ConvTranspose2d:(i,o,s)=>new M(this,i,o,s),DepthwiseConv2d:(i,o,s)=>new z(this,i,o,s),Add:(i,o)=>new D(this,i,o),Sigmoid:i=>new H(this,i),Tanh:i=>new R(this,i),ElementwiseMul:(i,o)=>new L(this,i,o),Warp:(i,o,s)=>new V(this,i,o,s),Stabilize:(i,o,s,u,l)=>new N(this,i,o,s,u,l),BilinearUpsample:(i,o)=>new $(this,i,o),Crop:(i,o)=>new j(this,i,o),BicubicUpsample:(i,o)=>new q(this,i,o),ChannelConcat:(i,o)=>new X(this,i,o),Conv2dAdd:(i,o,s,u)=>new K(this,i,o,s,u),ProjResidual:(i,o,s,u)=>new Y(this,i,o,s,u),ConcatConv2d:(i,o,s,u)=>new J(this,i,o,s,u),GatesFused:(i,o,s)=>new Q(this,i,o,s),CandUpdateFused:(i,o,s,u,l)=>new Z(this,i,o,s,u,l),ConvExpand:(i,o)=>new ee(this,i,o),CatConv6to2:(i,o,s)=>new te(this,i,o,s),DownAdapter:(i,o,s,u)=>new re(this,i,o,s,u),UpFinal:(i,o,s)=>new ne(this,i,o,s),UpFinalSkip:(i,o,s,u)=>new ae(this,i,o,s,u),UpsampleConcat:(i,o,s)=>new ie(this,i,o,s),UpsampleConv1x1:(i,o,s)=>new oe(this,i,o,s),UpsampleSigmoid:(i,o)=>new se(this,i,o),Input:(i,o)=>new de(this,i,o)},this.presenters={CompositeSolid:(i,o,s,u="main")=>{let l=new ue(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositeImage:(i,o,s,u="main")=>{let l=new pe(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositeImageBilinear:(i,o,s,u="main")=>{let l=new le(this,i,o,s);return {run:()=>{l.setOutput(this.getCurrentDisplayTexture(u)),l.run();}}},CompositePassthrough:(i,o="main")=>{let s=new ce(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:In,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(He(e)):new Float32Array(t).set(be(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"?be(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{_e as EffectsPipeline,xe as WebGPUBackend};