diff options
| author | skal <pascal.massimino@gmail.com> | 2026-03-22 17:47:17 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-03-22 17:47:17 +0100 |
| commit | 9bca6af775b723dd5bb972f6178516708abf58e2 (patch) | |
| tree | c179830be9c238ba20daca5b9ff17c6170d671e7 /cnn_v3/tools/tester.js | |
| parent | 3573654c3a60b8bd7545f4240273ed767699f1ae (diff) | |
feat(cnn_v3/tools): zoom canvas shows region around clicked texel
Diffstat (limited to 'cnn_v3/tools/tester.js')
| -rw-r--r-- | cnn_v3/tools/tester.js | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/cnn_v3/tools/tester.js b/cnn_v3/tools/tester.js index dbc7414..0412cae 100644 --- a/cnn_v3/tools/tester.js +++ b/cnn_v3/tools/tester.js @@ -465,7 +465,12 @@ class CNNv3Tester { const cvs=document.createElement('canvas'); const name=chName(c); cvs.title=name; - cvs.onclick=()=>tester.zoomChannel(id,c,name); + cvs.onclick=(e)=>{ + const r=cvs.getBoundingClientRect(); + const tx=Math.round(e.offsetX/r.width*tex.width); + const ty=Math.round(e.offsetY/r.height*tex.height); + tester.zoomChannel(id,c,name,tx,ty); + }; cell.appendChild(lbl); cell.appendChild(cvs); grid.appendChild(cell); } const pl=def.t==='f32'?this.getVizF32():this.getVizU32(); @@ -474,8 +479,8 @@ class CNNv3Tester { cvs.width=tex.width; cvs.height=tex.height; const ctx=cvs.getContext('webgpu'); if(!ctx)continue; try{ctx.configure({device:this.device,format:this.format});}catch(_){continue;} - const chBuf=this.device.createBuffer({size:4,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); - this.device.queue.writeBuffer(chBuf,0,new Uint32Array([c])); + const chBuf=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); + this.device.queue.writeBuffer(chBuf,0,new Int32Array([c,0,0,0])); const bg=this.device.createBindGroup({layout:pl.getBindGroupLayout(0), entries:[{binding:0,resource:tex.createView()},{binding:1,resource:{buffer:chBuf}}]}); const enc=this.device.createCommandEncoder(); @@ -487,13 +492,13 @@ class CNNv3Tester { await this.device.queue.onSubmittedWorkDone(); } - zoomChannel(layerId, ch, label) { + zoomChannel(layerId, ch, label, clickTx=0, clickTy=0) { const def = this.vizDefs?.find(d => d.id === layerId); const tex = this.layerTextures[layerId]; if (!def || !tex || !this.device) return; const wrap = document.getElementById('chzoomWrap'); const lbl = document.getElementById('chzoomLbl'); - this.activeZoom = {layerId, ch, label}; + this.activeZoom = {layerId, ch, label, clickTx, clickTy}; lbl.textContent = label; wrap.style.display = 'flex'; // Wait for layout so clientWidth/clientHeight reflect the flex-distributed size @@ -506,12 +511,17 @@ class CNNv3Tester { const scale = Math.min(1, availW / tex.width, availH / tex.height); dst.width = Math.round(tex.width * scale); dst.height = Math.round(tex.height * scale); - // Re-render via WebGPU (WebGPU canvas pixels are not readable by drawImage) + // Re-render via WebGPU centered on the clicked texel + const ox = clickTx - Math.floor(dst.width / 2); + const oy = clickTy - Math.floor(dst.height / 2); const pl = def.t === 'f32' ? this.getVizF32() : this.getVizU32(); const ctx = dst.getContext('webgpu'); try { ctx.configure({device: this.device, format: this.format}); } catch(_) { return; } - const chBuf = this.device.createBuffer({size:4, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); - this.device.queue.writeBuffer(chBuf, 0, new Uint32Array([ch])); + const uData = new ArrayBuffer(16); + const dv = new DataView(uData); + dv.setUint32(0, ch, true); dv.setInt32(8, ox, true); dv.setInt32(12, oy, true); + const chBuf = this.device.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); + this.device.queue.writeBuffer(chBuf, 0, uData); const bg = this.device.createBindGroup({layout: pl.getBindGroupLayout(0), entries:[{binding:0, resource:tex.createView()}, {binding:1, resource:{buffer:chBuf}}]}); const enc = this.device.createCommandEncoder(); @@ -525,8 +535,8 @@ class CNNv3Tester { refreshZoom() { if (this.activeZoom) { - const {layerId, ch, label} = this.activeZoom; - this.zoomChannel(layerId, ch, label); + const {layerId, ch, label, clickTx, clickTy} = this.activeZoom; + this.zoomChannel(layerId, ch, label, clickTx, clickTy); } } |
