Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Apr 28, 2024
1 parent 573771d commit 9163836
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
47 changes: 34 additions & 13 deletions docs/api-reference/core/luma.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,37 +100,42 @@ const webgpuDevice = luma.createDevice({

### `CreateDeviceProps`

Properties for creating a new device

```ts
type CreateDeviceProps = DeviceProps & {
/** 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 */
devices?: DeviceFactory[];
}
```
## Methods
### `AttachDeviceProps`
### `luma.registerDevices()`
Properties for attaching an existing WebGL context or WebGPU device to a new luma Device.
```typescript
luma.registerDevices(devices: (typeof Device)[]): void;
```ts
export type AttachDeviceProps = DeviceProps & {
/** Externally created WebGL context or WebGPU device */
handle: WebGL2RenderingContext | GPUDevice | null;
/** List of device types. Will also search any pre-registered device backends */
devices?: DeviceFactory[];
};
```

Registers one or more devices (device constructors) so that they can be used
to create `Device` instances against that GPU backend. The registered device types
will be available to `luma.createDevice()` and `luma.attachDevice()` calls.

`luma.registerDevices()` enables separation of the application code that
registers GPU backends from the application code that creates devices.
## Methods

### `luma.createDevice()`

```typescript
luma.createDevice({type, ...DeviceProps});
luma.createDevice({type, devices, ...deviceProps}: CreateDeviceProps);
```

To create a Device instance, the application calls `luma.createDevice()`.

- `type`: `'webgl' \| 'webgpu' \| 'best-available'`
- `devices`: list of `Device` backend classes. Can be omitted if `luma.registerDevices()` has been called.

Unless a device `type` is specified a `Device` will be created using the `'best-available'` adapter.
luma.gl favors WebGPU over WebGL devices, whenever WebGPU is available.
Expand All @@ -142,14 +147,30 @@ Note: A device type is available if:
### `luma.attachDevice()`

```ts
luma.attachDevice(handle: WebGL2RenderingContext | GPUDevice, devices: unknown[]);
luma.attachDevice({handle: WebGL2RenderingContext | GPUDevice, devices, ...}: 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.

If you need to attach a luma.gl `Device` to a WebGL 1 `WebGLRenderingContext`, see `luma.enforceWebGL2()`.
- `handle` - The externally created `WebGL2RenderingContext` or `GPUDevice` that should be attached to a luma `Device`.
- `devices` - list of `Device` backend classes. Can be omitted if `luma.registerDevices()` has been called.

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()`.

### `luma.registerDevices()`

```typescript
luma.registerDevices(devices?: (typeof Device)[]): void;
```

Registers one or more devices (device constructors) so that they can be used
to create `Device` instances against that GPU backend. The registered device types
will be available to `luma.createDevice()` and `luma.attachDevice()` calls.

`luma.registerDevices()` enables separation of the application code that
registers GPU backends from the application code that creates devices,
so that device types do not have to be provided at `Device` create or attach time.

### `luma.enforceWebGL2()`

Expand Down
6 changes: 4 additions & 2 deletions modules/core/src/adapter/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,10 @@ export type DeviceProps = {
_factoryDestroyPolicy?: 'unused' | 'never';
};

/** Used by Device registration */
export interface DeviceConstructor {
/**
* Create and attach devices for a specific backend. Currently static methods on each device
*/
export interface DeviceFactory {
// new (props: DeviceProps): Device; Constructor isn't used
type: string;
isSupported(): boolean;
Expand Down
21 changes: 12 additions & 9 deletions modules/core/src/adapter/luma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import type {Log} from '@probe.gl/log';
import type {DeviceProps} from './device';
import {Device, DeviceConstructor} from './device';
import {Device, DeviceFactory} from './device';
import {StatsManager} from '../utils/stats-manager';
import {lumaStats} from '../utils/stats-manager';
import {log} from '../utils/log';
Expand All @@ -16,14 +16,16 @@ const ERROR_MESSAGE =
export type CreateDeviceProps = DeviceProps & {
/** Selects the type of device. `best-available` uses webgpu if available, then webgl. */
type?: 'webgl' | 'webgpu' | 'unknown' | 'best-available';
devices?: DeviceConstructor[];
/** List of device types. Will also search any pre-registered device types */
devices?: DeviceFactory[];
};

/** Properties for attaching an existing WebGL context or WebGPU device to a new luma Device */
export type AttachDeviceProps = DeviceProps & {
/** Externally created WebGL context or WebGPU device */
handle: unknown; // WebGL2RenderingContext | GPUDevice | null;
devices?: DeviceConstructor[];
/** List of device types. Will also search any pre-registered device types */
devices?: DeviceFactory[];
};

/**
Expand All @@ -44,16 +46,16 @@ export class Luma {
/** Global log */
readonly log: Log = log;

protected deviceMap = new Map<string, DeviceConstructor>();
protected deviceMap = new Map<string, DeviceFactory>();

registerDevices(deviceClasses: DeviceConstructor[]): void {
registerDevices(deviceClasses: DeviceFactory[]): void {
for (const deviceClass of deviceClasses) {
this.deviceMap.set(deviceClass.type, deviceClass);
}
}

/** Get type strings for supported Devices */
getSupportedDeviceTypes(devices: DeviceConstructor[] = []): string[] {
getSupportedDeviceTypes(devices: DeviceFactory[] = []): string[] {
const deviceMap = this.getDeviceMap(devices);
return Array.from(deviceMap)
.map(([, Device]) => Device)
Expand All @@ -62,7 +64,7 @@ export class Luma {
}

/** Get type strings for best available Device */
getBestAvailableDeviceType(devices: DeviceConstructor[] = []): 'webgpu' | 'webgl' | null {
getBestAvailableDeviceType(devices: DeviceFactory[] = []): 'webgpu' | 'webgl' | null {
const deviceMap = this.getDeviceMap(devices);
if (deviceMap.get('webgpu')?.isSupported?.()) {
return 'webgpu';
Expand Down Expand Up @@ -108,7 +110,8 @@ export class Luma {
let deviceType;

// WebGPU sniffing
// eslint-disable-next-line GPUDevice type isn't generally available, we avoid enabling it in core
// GPUDevice type isn't generally available, we avoid enabling it in core
// eslint-disable-next-line no-undef
if (typeof GPUDevice !== 'undefined' && props.handle instanceof GPUDevice) {
deviceType = 'webgpu';
}
Expand Down Expand Up @@ -165,7 +168,7 @@ export class Luma {
}

/** Convert a list of devices to a map */
protected getDeviceMap(deviceClasses: DeviceConstructor[] = []): Map<string, DeviceConstructor> {
protected getDeviceMap(deviceClasses: DeviceFactory[] = []): Map<string, DeviceFactory> {
const map = new Map(this.deviceMap);
for (const deviceClass of deviceClasses) {
map.set(deviceClass.type, deviceClass);
Expand Down

0 comments on commit 9163836

Please sign in to comment.