nx_game_affine_emit_t38.nx
buildroot/runtime/nx_game_affine_emit_t38.nx
about
Private bridge emitter composed by the existing game-page owner. Deformation executes only in GPU compute.
dependencies 1 imports · 1 importers
imports: nx_cast_affine_compute_t38.nx
imported by: nx_game_affine_emit_gate_t38.nx
structs
| none |
consts
| 3 | const GAF_BRIDGE_T38:*u8="// AFM1 v1 runtime consumer. Caller verifies the enclosing NXA TOC and this section checksum.\nfunction nxAffineDecode(ab,section,nj){\n const dv=new DataView(ab), read=o=>{const n=Number(dv.getBigInt64(o,true));if(!Number.isSafeInteger(n))throw Error('AFM1 integer range');return n;};\n if(!section||!Number.isSafeInteger(section.o)||!Number.isSafeInteger(section.n)||section.o<0||section.o%8||section.n<8||section.n>(ab.byteLength-section.o)/8)throw Error('AFM1 extent');\n const o=section.o, h=Array.from({length:8},(_,i)=>read(o+i*8));\n if(h[0]!==1||h[2]!==nj||nj<1||h[3]<2||h[4]!==46186158000||h[5]<=0||h[6]<=0||h[7]!==1)throw Error('AFM1 version or contract');\n const stride=1+nj*12,base=8+nj;if(base+h[3]*stride!==section.n)throw Error('AFM1 shape');\n const ids=Array.from({length:nj},(_,i)=>read(o+(8+i)*8));if(new Set(ids).size!==nj)throw Error('AFM1 duplicate joint');\n const times=new Float64Array(h[3]),values=new Float64Array(h[3]*nj*12);\n for(let f=0;f<h[3];f++){const p=o+(base+f*stride)*8;const t=read(p);if(t<0||t>8796093022207||(f&&t<=times[f-1]))throw Error('AFM1 time');times[f]=t;\n for(let k=0;k<nj*12;k++){const v=read(p+(1+k)*8);if(Math.abs(v)>=4398046511103)throw Error('AFM1 coefficient');values[f*nj*12+k]=v/1048576;}}\n return {version:1,stackId:h[1],nj,frames:h[3],ticksPerSecond:h[4],times,values,ids,matrices:new Float64Array(nj*12),frame:-1};\n}\n\nfunction nxAffineDecodeSkin(ab,section,nv,nj){\n const dv=new DataView(ab),read=o=>{const n=Number(dv.getBigInt64(o,true));if(!Number.isSafeInteger(n))throw Error('SKV1 integer range');return n;};\n if(!section||!Number.isSafeInteger(section.o)||!Number.isSafeInteger(section.n)||section.o<0||section.o%8||section.n<4||section.n>(ab.byteLength-section.o)/8)throw Error('SKV1 extent');\n const o=section.o,version=read(o),vertices=read(o+8),count=read(o+16),q=read(o+24),base=4+nv+1;\n if(version!==1||vertices!==nv||count<nv||q!==281474976710656||base+count*2!==section.n)throw Error('SKV1 contract');\n const offsets=new Uint32Array(nv+1),records=new ArrayBuffer(count*8),rd=new DataView(records);\n for(let v=0;v<=nv;v++){const at=read(o+(4+v)*8);if(at<0||at>count||(v&&at<=offsets[v-1]))throw Error('SKV1 offsets');offsets[v]=at;}\n if(offsets[0]!==0||offsets[nv]!==count)throw Error('SKV1 boundary');\n for(let v=0;v<nv;v++){const seen=new Set();for(let i=offsets[v];i<offsets[v+1];i++){\n const j=read(o+(base+i*2)*8),w=read(o+(base+i*2+1)*8);if(j<0||j>=nj||seen.has(j)||w<=0)throw Error('SKV1 influence');seen.add(j);rd.setUint32(i*8,j,true);rd.setFloat32(i*8+4,w/q,true);if(!(rd.getFloat32(i*8+4,true)>0))throw Error('SKV1 float underflow');\n }}\n return {version,nv,count,offsets,records};\n}\nasync function nxGpuAffinePrepare(dev,D,P,clip,skin,axis,shader){\n if(clip.nj!==P.nj||skin.nv*3!==P.pos.length||P.nrm.length!==P.pos.length)throw Error('affine asset mismatch');\n if(dev.limits.maxStorageBuffersPerShaderStage<7||dev.limits.maxComputeInvocationsPerWorkgroup<64||dev.limits.maxComputeWorkgroupSizeX<64)throw Error('affine GPU limits');\n const source=new Float32Array(skin.nv*6);for(let v=0;v<skin.nv;v++){source.set(P.pos.subarray(v*3,v*3+3),v*6);source.set(P.nrm.subarray(v*3,v*3+3),v*6+3);}\n const matrices=Float32Array.from(clip.values),owned=[];\n const buffer=(data,usage)=>{if(data.byteLength>dev.limits.maxStorageBufferBindingSize||data.byteLength>dev.limits.maxBufferSize)throw Error('affine buffer budget');const b=dev.createBuffer({size:data.byteLength,usage:usage|GPUBufferUsage.COPY_DST,mappedAtCreation:true});owned.push(b);new Uint8Array(b.getMappedRange()).set(new Uint8Array(data.buffer||data,data.byteOffset||0,data.byteLength));b.unmap();return b;};\n try{\n const module=dev.createShaderModule({label:'nishi-cast-affine-v1',code:shader}),info=await module.getCompilationInfo();if(info.messages.some(m=>m.type==='error'))throw Error(info.messages.filter(m=>m.type==='error').map(m=>m.message).join('; '));\n const pipeline=await dev.createComputePipelineAsync({label:'nishi-cast-affine-v1',layout:'auto',compute:{module,entryPoint:'main'}});\n const params=new ArrayBuffer(32),pu=new Uint32Array(params),pf=new Float32Array(params);pu[0]=skin.nv;pu[1]=clip.nj;pu[5]=axis==='Y'?1:axis==='X'?2:0;\n const uniform=buffer(params,GPUBufferUsage.UNIFORM),inputs=buffer(source,GPUBufferUsage.STORAGE),offsets=buffer(skin.offsets,GPUBufferUsage.STORAGE),influences=buffer(skin.records,GPUBufferUsage.STORAGE),animation=buffer(matrices,GPUBufferUsage.STORAGE),faults=buffer(new Uint32Array(4),GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC);\n const group=dev.createBindGroup({layout:pipeline.getBindGroupLayout(0),entries:[uniform,inputs,offsets,influences,animation,D.bp,D.bn,faults].map((b,binding)=>({binding,resource:{buffer:b}}))});\n const prior=D.release;D.release=()=>{while(owned.length)owned.pop().destroy();prior();};\n D.affine={state:'prepared',pipeline,group,params,pu,pf,uniform,faults,clip,nv:skin.nv,started:performance.now(),submitted:0,scope:'GPU preparation; numerical execution and visible playback unqualified'};\n return D.affine;\n }catch(error){while(owned.length)owned.pop().destroy();throw error;}\n}\nfunction nxGpuAffineSubmit(dev,D,ticks){\n const a=D.affine;if(!a)throw Error('affine not prepared');const t=a.clip.times;if(!Number.isFinite(ticks)||ticks<t[0]||ticks>t[t.length-1])throw Error('affine time range');\n let lo=0,hi=t.length-1;while(lo+1<hi){const mid=(lo+hi)>>1;if(t[mid]<=ticks)lo=mid;else hi=mid;}\n a.pu[2]=lo;a.pu[3]=hi;a.pf[4]=(ticks-t[lo])/(t[hi]-t[lo]);dev.queue.writeBuffer(a.uniform,0,a.params);dev.queue.writeBuffer(a.faults,0,new Uint32Array(4));\n const encoder=dev.createCommandEncoder({label:'nishi-affine-skin'}),pass=encoder.beginComputePass({label:'nishi-affine-skin'});pass.setPipeline(a.pipeline);pass.setBindGroup(0,a.group);pass.dispatchWorkgroups(Math.ceil(a.nv/64));pass.end();dev.queue.submit([encoder.finish()]);a.submitted++;a.source_ticks=ticks;\n}\n" |
functions
| 4 | func gaf_copy(out:*u8,p0:i64,s:*u8)->i64{var p:i64=p0;var i:i64=0;while s[i]!=(0 as u8){out[p]=s[i];p=p+1;i=i+1};return p} |
| 5 | func gaf_quote(out:*u8,p0:i64,s:*u8)->i64 |
| 12 | func gaf_emit(out:*u8,p0:i64)->i64 |