// Read the four actual smooth textures without adding COPY_SRC usage to game resources. async function testSmoothInputs() { const d=GPU.device, code=` @group(0) @binding(0) var col: texture_2d; @group(0) @binding(1) var back: texture_2d; @group(0) @binding(2) var tree: texture_2d; @group(0) @binding(3) var field: texture_2d; @group(0) @binding(4) var out: array; @compute @workgroup_size(64) fn main(@builtin(global_invocation_id) id: vec3u) { let size=textureDimensions(col); let k=id.x; if(k>=size.x*size.y){return;} let p=vec2i(i32(k%size.x),i32(k/size.x)); out[k*4]=pack4x8unorm(textureLoad(col,p,0)); out[k*4+1]=pack4x8unorm(textureLoad(back,p,0)); out[k*4+2]=pack4x8unorm(textureLoad(tree,p,0)); out[k*4+3]=pack4x8unorm(textureLoad(field,p,0)); }`; const pipe=d.createComputePipeline({layout:'auto',compute:{module:d.createShaderModule({code}),entryPoint:'main'}}); const bytes=R.px.length*16; const storage=d.createBuffer({size:bytes,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}); const read=d.createBuffer({size:bytes,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}); const entries=[GPU.colourTex,GPU.backTex,GPU.treeTex,GPU.fieldTex].map((t,binding)=>({binding,resource:t.createView()})); entries.push({binding:4,resource:{buffer:storage}}); const bind=d.createBindGroup({layout:pipe.getBindGroupLayout(0),entries}); const enc=d.createCommandEncoder(),pass=enc.beginComputePass();pass.setPipeline(pipe);pass.setBindGroup(0,bind);pass.dispatchWorkgroups(Math.ceil(R.px.length/64));pass.end(); enc.copyBufferToBuffer(storage,0,read,0,bytes);d.queue.submit([enc.finish()]); await read.mapAsync(GPUMapMode.READ); const actual=new Uint32Array(read.getMappedRange()).slice(); read.unmap();storage.destroy();read.destroy(); return actual; }