Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(core) new device props api #2100

Merged
merged 24 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/api-guide/gpu/gpu-initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {luma} from '@luma.gl/core';
import {webgpuAdapter} from '@luma.gl/webgpu';

luma.registerAdapters([webgpuAdapter]);
const device = await luma.createDevice({type: 'webgpu', canvas: ...});
const device = await luma.createDevice({type: 'webgpu', canvasContext: {canvas: ...}});
```

It is possible to register more than one device adapter to create an application
Expand All @@ -65,5 +65,5 @@ import {WebGPUDevice} from '@luma.gl/webgpu';

luma.registerAdapters([WebGLDevice, WebGPUDevice]);

const webgpuDevice = luma.createDevice({type: 'best-available', canvas: ...});
const webgpuDevice = luma.createDevice({type: 'best-available', canvasContext: {canvas: ...}});
```
4 changes: 2 additions & 2 deletions docs/api-reference/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {luma} from '@luma.gl/core';
import {WebGPUAdapter} from '@luma.gl/webgpu';

luma.registerDevice([WebGPUAdapter])
const device = await luma.createDevice({type: 'webgpu', canvas: ...});
const device = await luma.createDevice({type: 'webgpu', canvasContext: ...});
```

It is possible to register more than one device adapter to create an application
Expand All @@ -26,7 +26,7 @@ import {luma} from '@luma.gl/core';
import {WebGPUAdapter} from '@luma.gl/webgpu';
import {WebGLAdapter} '@luma.gl/webgl';

const webgpuDevice = luma.createDevice({type: 'best-available', canvas: ...});
const webgpuDevice = luma.createDevice({type: 'best-available', canvasContext: ...});
```

## Creating GPU Resources
Expand Down
5 changes: 3 additions & 2 deletions docs/api-reference/core/canvas-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ const renderPass = device.beginRenderPass({
| `useDevicePixels?` | `boolean` \| `number` | Device pixels scale factor (`true` uses browser DPI) |
| `autoResize?` | `boolean` | Whether to track resizes |
| `visible?` | `boolean` | Visibility (only used if new canvas is created). |
| `colorSpace?` | `'srgb'` | WebGPU only https://www.w3.org/TR/webgpu/#canvas-configuration |
| `compositingAlphaMode?` | `'opaque'` \| `'premultiplied'` | WebGPU only https://www.w3.org/TR/webgpu/#canvas-configuration |
| `alphaMode?: string` | `'opaque'` | `'opaque' \| 'premultiplied'`. See [alphaMode](https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext/configure#alphamode). |
| `colorSpace?: 'string` | `'srgb'` | `'srgb' \| 'display-p3'`. See [colorSpace](https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext/configure#colorspace). |


## Static Fields

Expand Down
78 changes: 60 additions & 18 deletions docs/api-reference/core/device.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ with changes to enable a WebGL2 implementation.

## Usage

Create a new Device, auto creating a canvas and a new WebGL 2 context
Create a new `Device`, auto creating a canvas and a new WebGL 2 context. See [`luma.createDevice()`](./luma.md#lumacreatedevice).

```typescript
import {Device} from '@luma.gl/core';
const device = new luma.createDevice({type: 'webgl2'});
const device = new luma.createDevice({type: 'webgl2', ...});
```

Attaching a Device to an externally created `WebGL2RenderingContext`.
Attaching a `Device` to an externally created `WebGL2RenderingContext`.

```typescript
import {Device} from '@luma.gl/core';
import {Model} from '@luma.gl/engine';

const gl = canvas.createContext('webgl2');
const gl = canvas.getContext('webgl2', ...);
const device = Device.attach(gl);

const model = new Model(device, options);
Expand All @@ -52,20 +52,62 @@ console.error(message);

### `DeviceProps`

| Parameter | Default | Description |
| ------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `type` | `'best-available'` | `'webgpu'`, `'webgl'`, `'best-available'` |
| `canvas` | N/A | A _string_ `id` of an existing HTML element or a _DOMElement_. If not provided, a new canvas will be created. |
| priority. |
| `debug?: boolean` | `false` | WebGL API calls will be logged to the console and WebGL errors will generate JavaScript exceptions. |
| `break?: string[]` | `[]` | Insert a break point (`debugger`) if one of the listed gl functions is called. |
| `alpha?: boolean` | `true` | Default render target has an alpha buffer. |
| `depth?: boolean` | `true` | Default render target has a depth buffer of at least `16` bits. |
| `stencil?` | `false` | Default render target has a stencil buffer of at least `8` bits. |
| `antialias?` | `true` | Boolean that indicates whether or not to perform anti-aliasing. |
| `premultipliedAlpha?` | `true` | Boolean that indicates that the page compositor will assume the drawing buffer contains colors with pre-multiplied alpha. |
| `preserveDrawingBuffer?` | `false` | Default render target buffers will preserve their values until cleared or overwritten. Useful for screen capture. |
| `failIfMajorPerformanceCaveat?` | `false` | Do not create if the system performance is low. |
:::tip
This object can also include all [`CanvasContextProps`][canvas-context-props] properties to configure how a new canvas is created. If a canvas is provided, these are ignored.
:::

[canvas-context-props]: ./canvas-context.md#canvascontextprops
[webgl-attributes]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext#contextattributes

Specifies props to use when luma creates the device.

| Parameter | Default | Description |
| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `id?: string` | `null` | Optional string id, mainly intended for debugging. |
| `canvasContext?: CanvasContextProps` | [CanvasContexProps][canvas-context] | Props used to create the default `CanvasContext` for the new `Device`. |
chrisgervang marked this conversation as resolved.
Show resolved Hide resolved
| `onError?: (error: Error) => unknown` | `log.error` | Error handling. |
| `powerPreference?: string` | `'high-performance'` | `'default' \| 'high-performance' \| 'low-power'` (WebGL). |
| `webgl?: WebGLContextAttributes` | [`WebGLContextAttributes`][webgl-attributes] | Attributes passed on to WebGL (`canvas.getContext('webgl2', props.webgl)` |
| `_requestMaxLimits?: boolean` | `true` | Ensures that the Device exposes the highest `DeviceLimits` supported by platform (WebGPU). |
| `_initializeFeatures?: boolean` | `true` | Initialize all `DeviceFeatures` on startup. 🧪 |
| `_disabledFeatures?: Record<DeviceFeature, boolean>` | `{ 'compilation-status-async-webgl': true }` | Disable specific `DeviceFeatures`. 🧪 |
| `_factoryDestroyPolicy?: string` | `'unused'` | `'unused' \| 'never'` Never destroy cached shaders and pipelines. 🧪 |
Copy link
Contributor Author

@chrisgervang chrisgervang Aug 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why might someone use this?

It is a tradeoff between reuse/speed and memory. I added it to unblock things until we find the right balance.


:::caution
🧪 denotes experimental feature. Expect API to change.
:::

Specify WebGL debugging options to use when luma creates the WebGL context.

| WebGL Debugging | Default | Description |
| ---------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `debugShaders?`: `'errors'` \| `'warnings'` \| `'always'` \| `'never'` | `'error'` | Display shader source code with inline errors in the canvas. |
| `debugFramebuffers?: boolean` | `false` | Show small copy of the contents of updated Framebuffers in the canvas. |
| `debugWebGL?: boolean` | `false` | Initialize Khronos WebGLDeveloperTools. WebGL API calls will be logged to the console and WebGL errors will generate JavaScript exceptions. |
| `break?: string[]` | `[]` | Insert a break point (`debugger`) if one of the listed gl functions is called. |
chrisgervang marked this conversation as resolved.
Show resolved Hide resolved
| `debugSpectorJS?: boolean` | `false` | Initialize the SpectorJS WebGL debugger. |
| `debugSpectorJSUrl?: string` | N/A | SpectorJS URL. Override if CDN is down or different SpectorJS version is desired. |

:::tip
Learn more about WebGL debugging in our [Debugging](../../developer-guide/debugging.md) guide.
:::

#### WebGLContextAttributes

For detailed control over WebGL context can specify what [`WebGLContextAttributes`](webgl-attributes) to use if luma creates the WebGL context.

| `WebGLContextAttributes` | Default | Description |
| ---------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
| `webgl.preserveDrawingBuffers?: boolean` | `true` | Default render target buffers will preserve their values until overwritten. Useful for screen capture. |
| `webgl.alpha?: boolean` | `true` | Default render target has an alpha buffer. |
| `webgl.antialias?: boolean` | `true` | Boolean that indicates whether or not to perform anti-aliasing. |
| `webgl.depth?: boolean` | `true` | Default render target has a depth buffer of at least `16` bits. |
| `webgl.premultipliedAlpha?: boolean` | `true` | The page compositor will assume the drawing buffer contains colors with pre-multiplied alpha. |
| `webgl.stencil?: boolean` | `false` | Default render target has a stencil buffer of at least `8` bits. |
| `webgl.desynchronized?: boolean` | `false` | Hint to reduce latency by desynchronizing the canvas paint cycle from the event loop (WebGL). |
| `webgl.failIfMajorPerformanceCaveat?` | `false` | Do not create a Device if the system performance is low (WebGL). |

Note that luma.gl v9.1 and onwards set `webgl.preserveDrawingBuffers` to `true` by default. This can be disabled for some memory savings and a minor performance boost on resource limited devices, such as mobile phones, at the cost of not being able to take screenshots or render to screen without clearing.

## Fields

Expand Down
28 changes: 15 additions & 13 deletions docs/api-reference/core/luma.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ Create a WebGL 2 context (throws if WebGL2 not supported)
import {luma} from '@luma.gl/core';
import {webgl2Adapter} from '@luma.gl/webgl';

const webgpuDevice = luma.createDevice({type: 'webgl', adapters: [webgl2Adapter], canvas: ...});
const webgpuDevice = luma.createDevice({type: 'webgl', adapters: [webgl2Adapter], canvasContext: {canvas: ...}});
```

```typescript
const webgpuDevice = luma.createDevice({
type: 'best-available',
canvas: ...,
canvasContext: {...},
adapters: [webgl2Adapter, WebGPUDevice]
});
```
Expand All @@ -41,7 +41,7 @@ Register the WebGL backend, then create a WebGL2 context, auto creating a canvas
import {luma} from '@luma.gl/core';
import {webgl2Adapter} from '@luma.gl/webgl';
luma.registerAdapters([webgl2Adapter]);
const webglDevice = luma.createDevice({type: 'webgl', canvas: ...});
const webglDevice = luma.createDevice({type: 'webgl', canvasContext: {canvas: ...}});
```

It is possible to register more than one device to create an application
Expand All @@ -52,7 +52,7 @@ import {luma} from '@luma.gl/core';
import {webgl2Adapter} from '@luma.gl/webgl';
import {webgpuDevice} from '@luma.gl/webgl';
luma.registerAdapters([webgl2Adapter, webgpuDevice]);
const device = luma.createDevice({type: 'best-available', canvas: ...});
const device = luma.createDevice({type: 'best-available', canvasContext: {canvas: ...}});
```

## Registering Adapters
Expand All @@ -72,7 +72,7 @@ import {luma} from '@luma.gl/core';
import {webgpuAdapter} from '@luma.gl/webgpu';

luma.registerAdapters([webgpuAdapter]);
const device = await luma.createDevice({type: 'webgpu', canvas: ...});
const device = await luma.createDevice({type: 'webgpu', canvasContext: ...});
```

Pre-register devices
Expand All @@ -83,35 +83,35 @@ import {webgl2Adapter} from '@luma.gl/webgl';
import {webgpuAdapter} from '@luma.gl/webgpu';

luma.registerAdapters([webgl2Adapter, webgpuAdapter]);
const webgpuDevice = luma.createDevice({type: 'best-available', canvas: ...});
const webgpuDevice = luma.createDevice({type: 'best-available', canvasContext: ...});
```

## Types

### `CreateDeviceProps`

Properties for creating a new device
Properties for creating a new device. See [`DeviceProps`](./device.md#deviceprops) for device specific options.

```ts
type CreateDeviceProps = DeviceProps & {
type CreateDeviceProps = {
/** Selects the type of device. `best-available` uses webgpu if available, then webgl. */
type?: 'webgl' | 'webgpu' | 'unknown' | 'best-available';
/** List of device types. Will also search any pre-registered device backends */
adapters?: Adapter[];
}
} & DeviceProps
```

### `AttachDeviceProps`

Properties for attaching an existing WebGL context or WebGPU device to a new luma Device.
Properties for attaching an existing WebGL context or WebGPU device to a new luma Device. See [`DeviceProps`](./device.md#deviceprops) for device specific options.

```ts
export type AttachDeviceProps = DeviceProps & {
export type AttachDeviceProps = {
/** Externally created WebGL context or WebGPU device */
handle: WebGL2RenderingContext | GPUDevice | null;
/** List of device types. Will also search any pre-registered device backends */
adapters?: Adapter[];
};
} & DeviceProps;
```

## Methods
Expand All @@ -126,6 +126,7 @@ To create a Device instance, the application calls `luma.createDevice()`.

- `type`: `'webgl' \| 'webgpu' \| 'best-available'`
- `adapters`: list of `Adapter` instances providing support for different GPU backends. Can be omitted if `luma.registerAdapters()` has been called.
- `...deviceProps`: See [`DeviceProps`](./device.md#deviceprops) for device specific options.

Unless a device `type` is specified a `Device` will be created using the `'best-available'` adapter.
luma.gl favors WebGPU over WebGL adapters, whenever WebGPU is available.
Expand All @@ -137,14 +138,15 @@ Note: A specific device type is available and supported if both of the following
### `luma.attachDevice()`

```ts
luma.attachDevice({handle: WebGL2RenderingContext | GPUDevice, adapters, ...}: AttachDeviceProps);
luma.attachDevice({handle: WebGL2RenderingContext | GPUDevice, adapters, ...deviceProps}: AttachDeviceProps);
```

A luma.gl Device can be attached to an externally created `WebGL2RenderingContext` or `GPUDevice`.
This allows applications to use the luma.gl API to "interleave" rendering with other GPU libraries.

- `handle` - The externally created `WebGL2RenderingContext` or `GPUDevice` that should be attached to a luma `Device`.
- `adapters` - list of `Device` backend classes. Can be omitted if `luma.registerAdapters()` has been called.
- `...deviceProps`: See [`DeviceProps`](./device.md#deviceprops) for device specific options.

Note that while you cannot directly attach a luma.gl `Device` to a WebGL 1 `WebGLRenderingContext`, you may be able to work around it using `luma.enforceWebGL2()`.

Expand Down
2 changes: 1 addition & 1 deletion docs/api-reference/engine/compute/computation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Debug shader source (even when shader successful)
// construct the model.
const model = new Computation(device, {
source: COMPUTE_SHADER,
debugShaders: true
debugShaders: 'always'
});
```

Expand Down
2 changes: 1 addition & 1 deletion docs/api-reference/engine/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Debug shader source (even when shader successful)
const model = new Model(device, {
vs: VERTEX_SHADER,
fs: FRAGMENT_SHADER,
debugShaders: true
debugShaders: 'always'
});
```

Expand Down
10 changes: 5 additions & 5 deletions docs/api-reference/webgl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,33 @@
This module contains the WebGL adapter for the "abstract" luma.gl API (`@luma.gl/core`).

Simply importing `@luma.gl/webgl` installs the adapter and enables WebGL devices to
be created using `luma.createDevice(...)`:
be created using `luma.createDevice(props)`. See [`CreateDeviceProps`](../core/luma#createdeviceprops) for WebGL prop options.

```typescript
import {luma} from '@luma.gl/core';
import '@luma.gl/webgl'; // Installs the WebGLDevice adapter

const device = await luma.createDevice({type: 'webgl', canvas: ...});
const device = await luma.createDevice({type: 'webgl', canvasContext: {...}, webgl: {...}});

// Resources can now be created
const buffer = device.createBuffer(...);
```

To use a luma.gl WebGL `Device` with raw WebGL calls, the application needs to access
the `WebGLRenderingContext`. The context is available on the `WebGLDevice` subclass:
the `WebGL2RenderingContext`. The context is available on the `WebGLDevice` subclass:

```typescript
// @ts-expect-error
const gl = device.gl;
```

With a bit more work, typescript users can retrieve the `WebGLRenderingContext`
With a bit more work, typescript users can retrieve the `WebGL2RenderingContext`
without ignoring type errors:

```typescript
import {cast} from '@luma.gl/core';
import {WebGLDevice} from '@luma.gl/webgl'; // Installs the WebGLDevice adapter

const webglDevice = cast<WebGPUDevice>(device);
const webglDevice = cast<WebGLDevice>(device);
const gl = webglDevice.gl;
```
4 changes: 2 additions & 2 deletions docs/api-reference/webgpu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
This module contains the WebGPU adapter for the "abstract" luma.gl API (`@luma.gl/core`).

Simply importing `@luma.gl/webgpu` installs the adapter and enables WebGPU devices to
be created using `luma.createDevice(...)`:
be created using `luma.createDevice(props)`: See [`DeviceProps`](../core/luma#createdeviceprops) for WebGPU prop options.
chrisgervang marked this conversation as resolved.
Show resolved Hide resolved

```typescript
import {luma} from '@luma.gl/core';
import '@luma.gl/webgpu'; // Installs the WebGPUDevice adapter

const device = await luma.createDevice({type: 'webgpu', canvas: ...});
const device = await luma.createDevice({type: 'webgpu', canvasContext: {...}});

// Resources can now be created
const buffer = device.createBuffer(...);
Expand Down
Loading
Loading