Skip to content

feat(layers): Port ScatterplotLayer to WebGPU / WGSL #9432

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
12 changes: 10 additions & 2 deletions modules/core/src/lib/deck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {deepEqual} from '../utils/deep-equal';
import typedArrayManager from '../utils/typed-array-manager';
import {VERSION} from './init';

import {luma} from '@luma.gl/core';
import {luma, Adapter} from '@luma.gl/core';
import {webgl2Adapter} from '@luma.gl/webgl';
import {Timeline} from '@luma.gl/engine';
import {AnimationLoop} from '@luma.gl/engine';
Expand Down Expand Up @@ -117,6 +117,9 @@ export type DeckProps<ViewsT extends ViewOrViews = null> = {
/** Use an existing luma.gl GPU device. @note If not supplied, a new device will be created using props.deviceProps */
device?: Device | null;

/** Supply adapters to use when a new device is created */
adapters?: Adapter[];

/** A new device will be created using these props, assuming that an existing device is not supplied using props.device) */
deviceProps?: CreateDeviceProps;

Expand Down Expand Up @@ -373,16 +376,21 @@ export default class Deck<ViewsT extends ViewOrViews = null> {

// Create a new device
if (!deviceOrPromise) {
const canvasContextUserProps = this.props.deviceProps?.createCanvasContext;
const canvasContextProps =
typeof canvasContextUserProps === 'object' ? canvasContextUserProps : undefined;
// Create the "best" device supported from the registered adapters
const adapters = Array.from(new Set([...(props.adapters || []), webgl2Adapter]));
deviceOrPromise = luma.createDevice({
type: 'best-available',
// luma by default throws if a device is already attached
// asynchronous device creation could happen after finalize() is called
// TODO - createDevice should support AbortController?
_reuseDevices: true,
adapters: [webgl2Adapter],
adapters,
...props.deviceProps,
createCanvasContext: {
...canvasContextProps,
canvas: this._createCanvas(props),
useDevicePixels: this.props.useDevicePixels,
// TODO v9.2 - replace AnimationLoop's `autoResizeDrawingBuffer` with CanvasContext's `autoResize`
Expand Down
11 changes: 11 additions & 0 deletions modules/layers/src/line-layer/line-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
UpdateParameters,
DefaultProps
} from '@deck.gl/core';
import {Parameters} from '@luma.gl/core';
import {Model, Geometry} from '@luma.gl/engine';

import {lineUniforms, LineProps} from './line-layer-uniforms';
Expand Down Expand Up @@ -188,6 +189,15 @@ export default class LineLayer<DataT = any, ExtraProps extends {} = {}> extends
}

protected _getModel(): Model {
// TODO(ibgreen): WebGPU complication: Matching attachment state of the renderpass requires including a depth buffer
const parameters =
this.context.device.type === 'webgpu'
? ({
depthWriteEnabled: true,
depthCompare: 'less-equal'
} satisfies Parameters)
: undefined;

/*
* (0, -1)-------------_(1, -1)
* | _,-" |
Expand All @@ -207,6 +217,7 @@ export default class LineLayer<DataT = any, ExtraProps extends {} = {}> extends
positions: {size: 3, value: new Float32Array(positions)}
}
}),
parameters,
isInstanced: true
});
}
Expand Down
16 changes: 15 additions & 1 deletion modules/layers/src/scatterplot-layer/scatterplot-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
Color,
DefaultProps
} from '@deck.gl/core';
import {Parameters} from '@luma.gl/core';

const DEFAULT_COLOR: [number, number, number, number] = [0, 0, 0, 255];

Expand Down Expand Up @@ -257,10 +258,23 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
};
const model = this.state.model!;
model.shaderInputs.setProps({scatterplot: scatterplotProps});
if (this.context.device.type === 'webgpu') {
// @ts-expect-error TODO - this line was needed during WebGPU port
model.instanceCount = this.props.data.length;
}
model.draw(this.context.renderPass);
}

protected _getModel() {
// TODO(ibgreen): WebGPU complication: Matching attachment state of the renderpass requires including a depth buffer
const parameters =
this.context.device.type === 'webgpu'
? ({
depthWriteEnabled: true,
depthCompare: 'less-equal'
} satisfies Parameters)
: undefined;

// a square that minimally cover the unit circle
const positions = [-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0];
return new Model(this.context.device, {
Expand All @@ -273,7 +287,7 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
positions: {size: 3, value: new Float32Array(positions)}
}
}),
isInstanced: true
parameters
});
}
}
Loading