WebGPU Compute Bubblesort (1 thread)

JavaScript

async function main() {
  const adapter = await navigator.gpu?.requestAdapter();
  const hasTimer = adapter.features.has('timestamp-query');
  const device = await adapter?.requestDevice({
    requiredFeatures: hasTimer ? ['timestamp-query'] : [],
  });
  if (!device) {
    fail('need a browser that supports WebGPU');
    return;
  }
  device.addEventListener('uncapturederror', e => console.error(e.error.message));

  /* from wikipedia
    procedure bubbleSort(A : list of sortable items)
        n := length(A)
        repeat
            swapped := false
            for i := 1 to n-1 inclusive do
                { if this pair is out of order }
                if A[i-1] > A[i] then
                    { swap them and remember something changed }
                    swap(A[i-1], A[i])
                    swapped := true
                end if
            end for
        until not swapped
    end procedure
  */

  const module = device.createShaderModule({
    code: `
      @group(0) @binding(0) var<storage, read_write> a: array<f32>;

      @compute @workgroup_size(1) fn computeSomething() {
        let len = arrayLength(&a);
        var swapped: bool;
        loop {
          swapped = false;
          for (var i = 1u; i < len; i++) {
            if (a[i - 1] > a[i]) {
              let t = a[i];
              a[i] = a[i - 1];
              a[i - 1] = t;
              swapped = true;
            }
          }
          if (!swapped) {
            break;
          }
        }
      }
    `,
  });

  function bubblesort(a) {
    const len = a.length;
    let swapped;
    do {
      swapped = false;
      for (let i = 1; i < len; ++i) {
        if (a[i - 1] > a[i]) {
          let t = a[i];
          a[i] = a[i - 1];
          a[i - 1] = t;
          swapped = true;
        }
      }
    } while(swapped);
  }

 
  const pipeline = device.createComputePipeline({
    layout: 'auto',
    compute: {
      module,
    },
  });

  const numValues = 1000;
  const input =...