Directory portal: juejin.cn/post/701059…

instructions

WebGPU specification is described by WebIDL language, this paper mainly introduces the type definition.

Function definition and inheritance description are relatively simple, so they are omitted.

There are five types of syntax for defining types.

enum

An enumeration type, usually a JavaScript string with an enumeration value that matches any one of them.

enum GPUTextureDimension {
  "1d",
  "2d",
  "3d",
};
Copy the code

Thus, you can use this enumeration when creating texture objects:

const texture = device.createTexture({
  / *... * /
  dimension: "2d".// < -Dimension field is of type GPUTextureDimension
})
Copy the code

It’s not appropriate if you’re passing “36D.”

namespace

You need to access namespace. XXX, which is usually a binary number, or enumeration.

typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
[Exposed=(Window, DedicatedWorker)]
namespace GPUBufferUsage {
  const GPUFlagsConstant MAP_READ      = 0x0001;
  const GPUFlagsConstant MAP_WRITE     = 0x0002;
  const GPUFlagsConstant COPY_SRC      = 0x0004;
  const GPUFlagsConstant COPY_DST      = 0x0008;
  const GPUFlagsConstant INDEX         = 0x0010;
  const GPUFlagsConstant VERTEX        = 0x0020;
  const GPUFlagsConstant UNIFORM       = 0x0040;
  const GPUFlagsConstant STORAGE       = 0x0080;
  const GPUFlagsConstant INDIRECT      = 0x0100;
  const GPUFlagsConstant QUERY_RESOLVE = 0x0200;
};
Copy the code

When a GPUBuffer is created, its usage field can be set as follows:

const buffer = device.createBuffer({
  usage: GPUBufferUsage.UNIFORM,
  / *... * /
})
Copy the code

Since literals are binary numeric values, bitwise operations can be used to implement multiple type combinations:

const buffer = device.createBuffer({
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE,
  / *... * /
})
Copy the code

If you have friends who like to recite, it’s ok to memorize their values and assign them in literals (but it’s really stupid).

interface

Interfaces usually have a corresponding JavaScript Class, mostly created from device objects (channel encoders, adapters, and so on are not).

Most of them can be obtained in the browser Window environment and special webworkers.

Most of them require a corresponding descriptor, JavaScript Object, as a parameter.

const adapter = await navigator.gpu.requestAdapter()
console.log(adapter instanceof GPUAdapter) // true
Copy the code

Create action:

const device = await adapter.requestDevice()

const getBuffer = (desc: GPUBufferDescriptor): GPUBuffer= > {
  return device.createBuffer(desc)
}

const buffer = getBuffer({ / *... * / })
Copy the code

The above typescript code is a bit silly, but it’s enough to illustrate interfaces.

dictionary

A Dictionary represents a JavaScript Object.

// typescript

const bufferEntry: GPUBindGroupLayoutEntry = {
  binding: 0.visibility: GPUShaderStage.VERTEX,
  buffer: { /* All defaults, representing UBO */}}Copy the code

Sometimes it represents a descriptor, sometimes it represents the value of a field in a descriptor.

typedef

Defines an alias for a numeric type, similar to the macro definition in C.

typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;
typedef [EnforceRange] unsigned long GPUStencilValue;
typedef [EnforceRange] unsigned long GPUSampleMask;
typedef [EnforceRange] long GPUDepthBias;

typedef [EnforceRange] unsigned long long GPUSize64;
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
typedef [EnforceRange] unsigned long GPUIndex32;
typedef [EnforceRange] unsigned long GPUSize32;
typedef [EnforceRange] long GPUSignedOffset32;

typedef unsigned long GPUFlagsConstant;
Copy the code

These are the main types used.

Numeric types explain
unsigned long UInt32, accounting for 4 bytes
unsigned long long UInt64, accounts for 8 bytes
long UInt16, accounts for 2 bytes
float Float32, accounting for 4 bytes
double Float64, accounts for 8 bytes