Resizing the Context

Resizing and Re-Configuring the Context

The canvas's width and height set the texture size; CSS only stretches it. Setting them replaces the drawing buffer, and the next getCurrentTexture() has the new size without a new configure(). Sizes above maxTextureDimension2D fail validation, so clamp them. A ResizeObserver with devicePixelContentBoxSize gives the exact device-pixel size (Chrome 1 and Firefox 555 ; Safari 10 needs the CSS size times devicePixelRatio):

Keeping the canvas texture at device-pixel resolutionHTMLLive
<style>canvas { width: 100%; height: 60px; display: block }</style>
<canvas id="shelf"></canvas>
<script type="module">
  const device = await (await navigator.gpu.requestAdapter()).requestDevice();
  const context = shelf.getContext('webgpu');
  context.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });
  const clamp = (n) => Math.min(n, device.limits.maxTextureDimension2D);
  new ResizeObserver(([entry]) => {
    const css = entry.contentBoxSize[0], box = entry.devicePixelContentBoxSize?.[0];
    shelf.width = clamp(box?.inlineSize ?? Math.round(css.inlineSize * devicePixelRatio));
    shelf.height = clamp(box?.blockSize ?? Math.round(css.blockSize * devicePixelRatio));
    const t = context.getCurrentTexture();
    console.log(`CSS ${css.inlineSize}x${css.blockSize} -> texture ${t.width}x${t.height}`);
  }).observe(shelf);
</script>

Run with Chrome's display scale forced to 1.5 (--force-device-scale-factor=1.5):

Output of 27
CSS 464x60 -> texture 696x90

Redraw after a resize, since the contents are gone, and recreate depth and multisample textures to match (Depth and Multisampling). Draw from requestAnimationFrame, not the observer, so a drag still draws once per frame.