summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/common/util/navigator_gpu.ts
blob: 47cb1a4701c84b3c61bf719790bef8794632417a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/// <reference types="@webgpu/types" />

import { assert } from './util.js';

/**
 * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).
 * Throws an exception if not found.
 */
function defaultGPUProvider(): GPU {
  assert(
    typeof navigator !== 'undefined' && navigator.gpu !== undefined,
    'No WebGPU implementation found'
  );
  return navigator.gpu;
}

/**
 * GPUProvider is a function that creates and returns a new GPU instance.
 * May throw an exception if a GPU cannot be created.
 */
export type GPUProvider = () => GPU;

let gpuProvider: GPUProvider = defaultGPUProvider;

/**
 * Sets the function to create and return a new GPU instance.
 */
export function setGPUProvider(provider: GPUProvider) {
  assert(impl === undefined, 'setGPUProvider() should not be after getGPU()');
  gpuProvider = provider;
}

let impl: GPU | undefined = undefined;

let defaultRequestAdapterOptions: GPURequestAdapterOptions | undefined;

export function setDefaultRequestAdapterOptions(options: GPURequestAdapterOptions) {
  if (impl) {
    throw new Error('must call setDefaultRequestAdapterOptions before getGPU');
  }
  defaultRequestAdapterOptions = { ...options };
}

/**
 * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).
 * Throws an exception if not found.
 */
export function getGPU(): GPU {
  if (impl) {
    return impl;
  }

  impl = gpuProvider();

  if (defaultRequestAdapterOptions) {
    // eslint-disable-next-line @typescript-eslint/unbound-method
    const oldFn = impl.requestAdapter;
    impl.requestAdapter = function (
      options?: GPURequestAdapterOptions
    ): Promise<GPUAdapter | null> {
      const promise = oldFn.call(this, { ...defaultRequestAdapterOptions, ...(options || {}) });
      void promise.then(async adapter => {
        if (adapter) {
          const info = await adapter.requestAdapterInfo();
          // eslint-disable-next-line no-console
          console.log(info);
        }
      });
      return promise;
    };
  }

  return impl;
}