<canvas id="webgl" width="1" height="1"></canvas>
<canvas id="webgpu" width="1" height="1"></canvas>
<h3>Simulate 100w 4x4 Transform write/submit to GPU</h3>
<p>WebGL bufferSubData: <span id="t1"></span> ms</p>
<p>WebGPU writeBuffer: <span id="t2"></span> ms</p>
<p>WebGPU mapAsync: <span id="t3"></span> ms</p>
async function init() {
  // simulate 100w 4x4 tranform matrix
  const DATA = new Float32Array(1000000 * 16).fill(1);
  const t1 = document.querySelector("#t1");
  const t2 = document.querySelector("#t2");
  const t3 = document.querySelector("#t3");

  const canvas = document.getElementById("webgl");
  const gl = canvas.getContext("webgl");
  const buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, DATA.byteLength, gl.DYNAMIC_DRAW);

  if (!("gpu" in navigator)) throw new Error("WebGPU is not supported");
  const adapter = await navigator.gpu.requestAdapter({
    powerPreference: "high-performance"
  });
  if (!adapter) throw new Error("no gpu adapter found");
  const device = await adapter.requestDevice();
  const GPUBuffer1 = device.createBuffer({
    label: "Test Buffer",
    size: DATA.byteLength,
    usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
  });
  const GPUBuffer2 = device.createBuffer({
    label: "temp Buffer",
    size: DATA.byteLength,
    usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC
  });

  function testWebgl() {
    const start = performance.now();
    gl.bufferSubData(gl.ARRAY_BUFFER, 0, DATA);
    const dur = (performance.now() - start).toFixed(4);
    t1.innerHTML = dur;
    console.log("webgl bufferData:", dur + "ms");
  }

  function testWebGPU() {
    const start = performance.now();
    device.queue.writeBuffer(GPUBuffer1, 0, DATA);
    const dur = (performance.now() - start).toFixed(4);
    t2.innerHTML = dur;
    console.log("webGPU writebuffer:", dur + "ms");
  }

  async function testMapAysnc() {
    const start = performance.now();
    await GPUBuffer2.mapAsync(GPUMapMode.WRITE);
    new Float32Array(GPUBuffer2.getMappedRange()).set(DATA);
    GPUBuffer2.unmap();
    const dur = (performance.now() - start).toFixed(4);
    t3.innerHTML = dur;
    console.log("webGPU mapAsync:", dur + "ms");
  }

  async function sleep(dur) {
    return new Promise((res) => {
      setTimeout(() => {
        res(true);
      }, dur || 200);
    });
  }
  setInterval(async () => {
    testWebgl()
    testWebGPU()
    await testMapAysnc()
  }, 1000);
}

init();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.