import"./modulepreload-polyfill-B5Qt9EMX.js";import{j as S,r as x}from"./index-CMkL1IIy.js";import{c as ve}from"./client-CiuGHKKk.js";import{b as xe,O as Me,a as re,c as be}from"./OrtWorkerClient-BX-dwmm6.js";import{p as Re,b as Fe,c as Ie,i as $e}from"./preprocess-Dn1t3C7G.js";import{s as Oe,f as Ge,a as Le}from"./flowSampler-73rRJlES.js";import{t as V}from"./ImageToGaussianModel-Buc7WHZd.js";import{a as Ne}from"./octree-CtLanPnB.js";const Be={dinov3:"dinov3_encoder_fp32.onnx",vaeEncoder:"flux2_vae_encoder.onnx",dit:"dit_step_webgpu_fp32.onnx",octree:"octree_occupancy_decoder_fp32.onnx",gaussianDecoder:"gaussian_decoder_fp32.onnx"};function me(e){return e.endsWith("/")?e:`${e}/`}function Ce(){return me("/models/triposplat/")}function De(e={}){const t=me(e.baseUrl?.trim()||Ce()),n=["dinov3","vaeEncoder","dit","octree","gaussianDecoder"],r={};for(const s of n){const a=Be[s];r[s]={internalPrecision:"float32",precision:s==="vaeEncoder"?e.vaeInputPrecision??"float32":"float32",manifest:{graphUrl:`${t}${a}`,externalData:[{path:`${a}.data`,url:`${t}${a}.data`}]}}}return r}function Ue(e="/models/triposplat/flux2_vae_encoder.onnx",t="float32"){return{vaeEncoder:{precision:t,manifest:xe(e,{externalDataPath:"flux2_vae_encoder.onnx.data"})}}}const ke=new Float32Array([1,0,0,0,0,-1,0,1,0]),oe=["x","y","z","nx","ny","nz","f_dc_0","f_dc_1","f_dc_2","opacity","scale_0","scale_1","scale_2","rot_0","rot_1","rot_2","rot_3"];function qe(e){return Math.min(1-1e-6,Math.max(1e-6,e))}function je(e){const t=e.opacities.length;if(e.positions.length!==t*3)throw new Error("positions length must equal count * 3.");if(e.scales.length!==t*3)throw new Error("scales length must equal count * 3.");if(e.rotations.length!==t*4)throw new Error("rotations length must equal count * 4.");if(e.sh0.length!==t*3)throw new Error("sh0 length must equal count * 3.");return t}function He(e,t,n,r){const s=1/(Math.hypot(e,t,n,r)||1);return e*=s,t*=s,n*=s,r*=s,new Float64Array([1-2*(n*n+r*r),2*(t*n-e*r),2*(t*r+e*n),2*(t*n+e*r),1-2*(t*t+r*r),2*(n*r-e*t),2*(t*r-e*n),2*(n*r+e*t),1-2*(t*t+n*n)])}function We(e,t){const n=new Float64Array(9);for(let r=0;r<3;r+=1)for(let s=0;s<3;s+=1)n[r*3+s]=e[r*3]*t[s]+e[r*3+1]*t[3+s]+e[r*3+2]*t[6+s];return n}function Ve(e){const t=e[0],n=e[4],r=e[8],s=t+n+r;let a,l,c,u;if(s>0){const o=Math.sqrt(s+1)*2;a=.25*o,l=(e[7]-e[5])/o,c=(e[2]-e[6])/o,u=(e[3]-e[1])/o}else if(t>=n&&t>=r){const o=Math.sqrt(Math.max(0,1+t-n-r))*2||1;a=(e[7]-e[5])/o,l=.25*o,c=(e[1]+e[3])/o,u=(e[2]+e[6])/o}else if(n>=r){const o=Math.sqrt(Math.max(0,1+n-t-r))*2||1;a=(e[2]-e[6])/o,l=(e[1]+e[3])/o,c=.25*o,u=(e[5]+e[7])/o}else{const o=Math.sqrt(Math.max(0,1+r-t-n))*2||1;a=(e[3]-e[1])/o,l=(e[2]+e[6])/o,c=(e[5]+e[7])/o,u=.25*o}const i=1/(Math.hypot(a,l,c,u)||1);return[a*i,l*i,c*i,u*i]}function Xe(e){const t=je(e),n=["ply","format binary_little_endian 1.0",`element vertex ${t}`,...oe.map(u=>`property float ${u}`),"end_header",""].join(` `),r=new TextEncoder().encode(n),s=oe.length*4,a=new Uint8Array(r.length+t*s);a.set(r);const l=new DataView(a.buffer);let c=r.length;for(let u=0;ut*n,1)}const M=32,J=480,Je=0,Ye=96,ze=192,Ke=288,Ze=416,Qe=448,et=.75,ce=9e-4,tt=Math.log(.1/.9),nt=we(.004),rt=we(.05),ot=at();function we(e){return Math.log(Math.expm1(e))}function le(e){return e>20?e:e<-20?Math.exp(e):Math.log1p(Math.exp(e))}function st(e){if(e>=0)return 1/(1+Math.exp(-e));const t=Math.exp(e);return t/(1+t)}function de(e,t){let n=0,r=1/e,s=t;for(;s>0;)n+=s%e*r,s=Math.floor(s/e),r/=e;return n}function at(){const e=new Float32Array(M*3);for(let t=0;t>>0}next(){this.state=this.state+1831565813>>>0;let t=this.state;return t=Math.imul(t^t>>>15,t|1),t^=t+Math.imul(t^t>>>7,t|61),((t^t>>>14)>>>0)/4294967296}}function X(e,t){let n=0;for(;n{const h=await this.client.runSession({sessionId:I.dit,inputs:{latent:E(o,p.sample.latent,C),camera:E(o,p.sample.camera,ee),t:E(o,new Float32Array(p.timestepTensor),[1]),feature1:E(o,new Float32Array(p.condition.feature1),Z),feature2:E(o,new Float32Array(p.condition.feature2),Q)},outputs:["pred_latent","pred_camera"],tag:`flow-${p.pass}-${p.step}-of-${p.totalSteps}`});g+=h.timings.inferenceMs,A+=h.timings.readbackMs;const T=h.outputs.pred_latent,R=h.outputs.pred_camera;if(!T||!R)throw new Error("DiT graph must return pred_latent and pred_camera.");return{latent:$("pred_latent",T),camera:$("pred_camera",R)}},{latent:u,camera:i},{condition:l,negativeCondition:c,steps:_,guidanceScale:n.guidanceScale??3,shift:n.shift??3,predictionArithmetic:o.internalPrecision==="float32"?"float32":"float16",signal:n.signal,onStep:({step:p,totalSteps:h})=>{n.onProgress?.({stage:"sampling",message:`TripoSplat flow step ${p}/${h}…`,progress:p/h,step:p,totalSteps:h})}})}finally{await this.disposeGraph("dit")}const P=this.normalizeGaussianCount(n.numGaussians??D),d=P/M,w=this.requireGraph("octree");await this.loadGraph("octree");let b=0;n.onProgress?.({stage:"decoding-octree",message:"Sampling the dynamic occupancy octree…"});let v;try{v=await Ne(async p=>{const h=new Float32Array(ae*3);h.set(p.parentCenters);const T=await this.client.runSession({sessionId:I.octree,inputs:{x:E(w,h,[1,ae,3]),l:E(w,Float32Array.of(p.resolution),[1]),cond:E(w,new Float32Array(p.condition),C)},outputs:["logits"],tag:`octree-level-${p.level}`});b+=T.timings.inferenceMs;const R=T.outputs.logits;if(!R)throw new Error("Octree graph did not return logits.");const G=$("logits",R),L=p.parentCount*8;if(G.lengthr.next(),signal:n.signal,onLevel:({level:p,totalLevels:h,occupiedVoxels:T})=>{n.onProgress?.({stage:"decoding-octree",message:`Octree level ${p}/${h}: ${T.toLocaleString()} occupied voxels…`,progress:p/h})}})}finally{await this.disposeGraph("octree")}const U=this.requireGraph("gaussianDecoder");await this.loadGraph("gaussianDecoder"),n.onProgress?.({stage:"decoding-gaussians",message:"Decoding Gaussian attributes…"});let O,k=0;try{const p=await this.client.runSession({sessionId:I.gaussianDecoder,inputs:{points:E(U,new Float32Array(v.points),[1,d,3]),cond:E(U,new Float32Array(f.latent),C)},outputs:["features"]});k=p.timings.inferenceMs;const h=p.outputs.features;if(!h)throw new Error("Gaussian decoder graph did not return features.");O=$("features",h)}finally{await this.disposeGraph("gaussianDecoder")}this.assertLength("Gaussian decoder features",O,d*J);const q=it(v.points,O);n.onProgress?.({stage:"building-ply",message:"Building browser Gaussian PLY…"});const j=Xe(q);return{model:"triposplat",count:P,totalCount:P,ply:j,gaussians:q,coordinateSystem:"triposplat-object",colorSpace:"sh0",metadata:{steps:_,guidanceScale:n.guidanceScale??3,shift:n.shift??3,seed:n.seed??42,ditInferenceMs:g,ditReadbackMs:A,octreeInferenceMs:b,gaussianInferenceMs:k}}}async dispose(){this.disposed||(this.disposed=!0,this.sessions.clear(),await this.client.dispose())}async loadGraph(t){const n=this.sessions.get(t);if(n)return n;const r=this.requireGraph(t),s=await this.client.loadSession({sessionId:I[t],manifest:r.manifest,options:{allowWasmFallback:this.allowWasmFallback,graphOptimizationLevel:"disabled"}});return this.sessions.set(t,s),s}async disposeGraph(t){this.sessions.delete(t)&&await this.client.disposeSession(I[t])}requireGraph(t){const n=this.graphs[t];if(!n)throw new Error(`TripoSplat graph '${t}' is not configured.`);return n}assertLength(t,n,r){if(n.length!==r)throw new Error(`${t} contains ${n.length} values; expected ${r}.`)}normalizeGaussianCount(t){if(!Number.isFinite(t)||tD)throw new Error(`numGaussians must be in [${ie}, ${D}].`);const n=Math.round(t/M)*M;if(n!==D)throw new Error(`The checked-in Gaussian decoder contract is fixed at ${D} Gaussians (8192 decoder points); requested ${n}. Export a separate fixed-shape decoder to support another count without changing full self-attention semantics.`);return n}assertUsable(){if(this.disposed)throw new Error("TripoSplatWebGPUModel has been disposed.")}}const lt="/models/triposplat/flux2_vae_encoder.onnx",dt="/fixtures/generated/flux2-vae-fp32",pe=3;async function he(e){const t=await fetch(e);if(!t.ok)throw new Error(`Could not fetch ${e}: HTTP ${t.status}`);const n=await t.arrayBuffer();if(n.byteLength%4!==0)throw new Error(`${e} is not aligned float32 data.`);return new Float32Array(n)}function fe(e){const t=[...e].sort((r,s)=>r-s),n=Math.floor(t.length/2);return t.length%2===0?(t[n-1]+t[n])/2:t[n]}function ut(e,t){if(e.length!==t.length)throw new Error(`Prepared RGB length ${t.length} does not match Python ${e.length}.`);let n=0,r=0,s=0;for(let l=0;l=0?n:void 0}catch{return}}function ht(){const e=x.useRef(null),[t,n]=x.useState(lt),[r,s]=x.useState(dt),[a,l]=x.useState("Ready to run the recorded PyTorch fixture."),[c,u]=x.useState(!1),[i,o]=x.useState(null),[g,A]=x.useState(null);x.useEffect(()=>()=>{const f=e.current;e.current=null,f&&f.dispose()},[]);const _=async()=>{if(c)return;u(!0),A(null),o(null),delete window.__TRIPOSPLAT_ENCODER_RESULT__;let f="unknown";const P=d=>{l(d.message),d.executionProvider&&(f=d.executionProvider)};try{const d=e.current;e.current=null,d&&await d.dispose();const w=new ct({graphs:Ue(t,"float32"),allowWasmFallback:!1,onRuntimeStatus:P});e.current=w,l("Fetching the prepared image, explicit epsilon and PyTorch reference…");const[b,v,U,O,k]=await Promise.all([fetch(`${r}/source.png`),fetch(`${r}/prepared.png`),he(`${r}/epsilon.f32`),he(`${r}/feature2.f32`),pt()]);if(!b.ok)throw new Error(`Could not fetch fixture image: HTTP ${b.status}`);if(!v.ok)throw new Error(`Could not fetch prepared reference: HTTP ${v.status}`);const q=await b.blob(),j=await createImageBitmap(await v.blob()),p=(()=>{try{return Ie($e(j)).data}finally{j.close()}})(),h=w.graphs.vaeEncoder?.manifest,T=h?await Promise.all([ge(h.graphUrl),...(h.externalData??[]).map(({url:m})=>ge(m))]):[],R=T.length>0&&T.every(m=>m!==void 0)?T.reduce((m,W)=>m+(W??0),0):void 0,G=await te(),L=performance.now();await w.load();const Se=performance.now()-L,ye=await te(),F=[];let H;for(let m=1;m<=pe;m+=1){const W=await createImageBitmap(q),Te=performance.now(),N=await(async()=>{try{return await w.encode(W,{vaeNoise:U,onProgress:Pe=>l(`Run ${m}/${pe}: ${Pe.message}`)})}finally{W.close()}})(),_e=performance.now()-Te;if(!N.feature2||!N.timings.vaeEncoder)throw new Error("The VAE slice returned no feature2 tensor or runtime timings.");H||(H=new Uint8ClampedArray(N.preparedImage.data)),F.push({run:m,endToEndEncodeMs:_e,runtime:N.timings.vaeEncoder,comparison:be(O,N.feature2)})}const Ae=await te(),Y=F[F.length-1];if(!H)throw new Error("Browser preprocessing returned no prepared RGB image.");const ne=ut(p,H),z={maxAbsoluteError:.006,minimumCosineSimilarity:.99999},K={passed:ne.passed&&F.every(({comparison:m})=>m.finite&&m.maxAbsoluteError<=z.maxAbsoluteError&&m.cosineSimilarity>=z.minimumCosineSimilarity),executionProvider:f,modelLoadMs:Se,endToEndEncodeMs:Y.endToEndEncodeMs,runtime:Y.runtime,comparison:Y.comparison,preprocessing:ne,runs:F,medianInferenceMs:fe(F.map(({runtime:m})=>m.inferenceMs)),medianEndToEndEncodeMs:fe(F.map(({endToEndEncodeMs:m})=>m)),modelTransferBytes:R,memory:{beforeLoad:G,afterLoad:ye,afterRuns:Ae},environment:k,tolerance:z};window.__TRIPOSPLAT_ENCODER_RESULT__=K,o(K),l(K.passed?"PASS: WebGPU output matches the recorded PyTorch tensor.":"FAIL: tensor drift exceeds tolerance.")}catch(d){const w=d instanceof Error?d.message:String(d);A(w),l("Encoder validation failed.")}finally{u(!1)}};return S.jsxs("main",{children:[S.jsx("h1",{children:"TripoSplat Flux VAE · WebGPU parity"}),S.jsx("p",{children:"This page runs the recorded alpha-present source image through browser preprocessing, then sends the resulting 1024² tensor and explicit epsilon through ONNX Runtime WebGPU."}),S.jsxs("label",{children:["ONNX graph ",S.jsx("input",{value:t,onChange:f=>n(f.target.value)})]}),S.jsxs("label",{children:["Fixture directory ",S.jsx("input",{value:r,onChange:f=>s(f.target.value)})]}),S.jsx("button",{type:"button",disabled:c,onClick:()=>{_()},children:c?"Running…":"Run parity gate"}),S.jsx("p",{role:"status","data-testid":"encoder-status",children:a}),g?S.jsx("pre",{className:"error","data-testid":"encoder-error",children:g}):null,i?S.jsx("pre",{"data-testid":"encoder-result",children:JSON.stringify(i,null,2)}):null]})}const Ee=document.createElement("style");Ee.textContent=` :root { color: #ececf3; background: #101014; font: 15px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; } body { margin: 0; } main { max-width: 920px; margin: 0 auto; padding: 48px 24px; } h1 { font: 600 28px/1.2 system-ui, sans-serif; } label { display: grid; gap: 6px; margin: 18px 0; } input { box-sizing: border-box; width: 100%; padding: 10px; color: inherit; background: #1b1b22; border: 1px solid #3a3a48; border-radius: 6px; } button { padding: 10px 16px; color: #08080a; background: #f8cf00; border: 0; border-radius: 6px; font-weight: 700; cursor: pointer; } button:disabled { opacity: .55; cursor: wait; } pre { overflow: auto; padding: 16px; background: #18181f; border-radius: 8px; } .error { color: #ff9b9b; } `;document.head.append(Ee);ve.createRoot(document.getElementById("root")).render(S.jsx(x.StrictMode,{children:S.jsx(ht,{})}));