@luma.gl/webgpu 9.0.0-alpha.34 → 9.0.0-alpha.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +2 -2
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +23 -4
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +3 -2
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +11 -12
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +1 -1
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.d.ts +26 -0
- package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-vertex-array.js +39 -0
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -0
- package/dist/adapter/webgpu-canvas-context.d.ts +8 -2
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +11 -10
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +4 -1
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +10 -14
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/dist.dev.js +250 -110
- package/dist/index.cjs +130 -59
- package/dist.min.js +5 -5
- package/package.json +3 -3
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +1 -0
- package/src/adapter/helpers/webgpu-parameters.ts +2 -2
- package/src/adapter/resources/webgpu-render-pass.ts +27 -4
- package/src/adapter/resources/webgpu-render-pipeline.ts +18 -15
- package/src/adapter/resources/webgpu-shader.ts +1 -1
- package/src/adapter/resources/webgpu-texture.ts +7 -0
- package/src/adapter/resources/webgpu-vertex-array.ts +73 -0
- package/src/adapter/webgpu-canvas-context.ts +36 -16
- package/src/adapter/webgpu-device.ts +21 -13
|
@@ -32,13 +32,20 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
32
32
|
// private _lastIndex: number;
|
|
33
33
|
|
|
34
34
|
/** For internal use to create BindGroups */
|
|
35
|
-
private _bindGroupLayout: GPUBindGroupLayout;
|
|
35
|
+
private _bindGroupLayout: GPUBindGroupLayout | null = null;
|
|
36
36
|
private _bindGroup: GPUBindGroup | null = null;
|
|
37
37
|
|
|
38
38
|
constructor(device: WebGPUDevice, props: RenderPipelineProps) {
|
|
39
39
|
super(device, props);
|
|
40
40
|
this.device = device;
|
|
41
|
-
this.handle =
|
|
41
|
+
this.handle = this.props.handle as GPURenderPipeline;
|
|
42
|
+
if (!this.handle) {
|
|
43
|
+
const descriptor = this._getRenderPipelineDescriptor();
|
|
44
|
+
log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
|
|
45
|
+
log.probe(1, JSON.stringify(descriptor, null, 2))();
|
|
46
|
+
log.groupEnd(1)();
|
|
47
|
+
this.handle = this.device.handle.createRenderPipeline(descriptor);
|
|
48
|
+
}
|
|
42
49
|
this.handle.label = this.props.id;
|
|
43
50
|
|
|
44
51
|
this.vs = cast<WebGPUShader>(props.vs);
|
|
@@ -46,16 +53,6 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
46
53
|
|
|
47
54
|
this._bufferSlots = getBufferSlots(this.props.shaderLayout, this.props.bufferLayout);
|
|
48
55
|
this._buffers = new Array<Buffer>(Object.keys(this._bufferSlots).length).fill(null);
|
|
49
|
-
this._bindGroupLayout = this.handle.getBindGroupLayout(0);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
protected createHandle(): GPURenderPipeline {
|
|
53
|
-
const descriptor = this._getRenderPipelineDescriptor();
|
|
54
|
-
const renderPipeline = this.device.handle.createRenderPipeline(descriptor);
|
|
55
|
-
log.groupCollapsed(1, `new WebGPRenderPipeline(${this.id})`)();
|
|
56
|
-
log.log(1, JSON.stringify(descriptor, null, 2))();
|
|
57
|
-
log.groupEnd(1)();
|
|
58
|
-
return renderPipeline;
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
override destroy(): void {
|
|
@@ -91,7 +88,12 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
91
88
|
|
|
92
89
|
setBindings(bindings: Record<string, Binding>): void {
|
|
93
90
|
if (!isObjectEmpty(this.props.bindings)) {
|
|
91
|
+
// Do we want to save things on CPU side?
|
|
94
92
|
Object.assign(this.props.bindings, bindings);
|
|
93
|
+
|
|
94
|
+
// Get hold of the bind group layout. We don't want to do this unless we know there is at least one bind group
|
|
95
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
96
|
+
|
|
95
97
|
// Set up the bindings
|
|
96
98
|
this._bindGroup = getBindGroup(
|
|
97
99
|
this.device.handle,
|
|
@@ -118,7 +120,9 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
118
120
|
return this._bindGroup;
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
125
|
+
*/
|
|
122
126
|
protected _getRenderPipelineDescriptor() {
|
|
123
127
|
// Set up the vertex stage
|
|
124
128
|
const vertex: GPUVertexState = {
|
|
@@ -203,8 +207,7 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
203
207
|
} else {
|
|
204
208
|
webgpuRenderPass.handle.draw(
|
|
205
209
|
options.vertexCount || 0,
|
|
206
|
-
options.instanceCount,
|
|
207
|
-
options.firstIndex,
|
|
210
|
+
options.instanceCount || 1, // If 0, nothing will be drawn
|
|
208
211
|
options.firstInstance
|
|
209
212
|
);
|
|
210
213
|
}
|
|
@@ -47,7 +47,7 @@ export class WebGPUShader extends Shader {
|
|
|
47
47
|
|
|
48
48
|
let language = this.props.language;
|
|
49
49
|
// Compile from src
|
|
50
|
-
if (
|
|
50
|
+
if (language === 'auto') {
|
|
51
51
|
// wgsl uses C++ "auto" style arrow notation
|
|
52
52
|
language = source.includes('->') ? 'wgsl' : 'glsl';
|
|
53
53
|
}
|
|
@@ -45,6 +45,13 @@ export class WebGPUTexture extends Texture {
|
|
|
45
45
|
|
|
46
46
|
this.width = this.handle.width;
|
|
47
47
|
this.height = this.handle.height;
|
|
48
|
+
// Why not just read all properties directly from the texture
|
|
49
|
+
// this.depthOrArrayLayers = this.handle.depthOrArrayLayers;
|
|
50
|
+
// this.mipLevelCount = this.handle.mipLevelCount;
|
|
51
|
+
// this.sampleCount = this.handle.sampleCount;
|
|
52
|
+
// this.dimension = this.handle.dimension;
|
|
53
|
+
// this.format = this.handle.format;
|
|
54
|
+
// this.usage = this.handle.usage;
|
|
48
55
|
|
|
49
56
|
// Create a default sampler. This mimics the WebGL1 API where sampler props are stored on the texture
|
|
50
57
|
// this.setSampler(props.sampler);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
|
|
3
|
+
import type {Device, Buffer, VertexArrayProps, RenderPass, TypedArray} from '@luma.gl/core';
|
|
4
|
+
import {VertexArray, log} from '@luma.gl/core';
|
|
5
|
+
import {getBrowser} from '@probe.gl/env';
|
|
6
|
+
|
|
7
|
+
import {WebGPUDevice} from '../webgpu-device';
|
|
8
|
+
import {WebGPUBuffer} from '../resources/webgpu-buffer';
|
|
9
|
+
|
|
10
|
+
import {WebGPURenderPass} from './webgpu-render-pass';
|
|
11
|
+
|
|
12
|
+
/** VertexArrayObject wrapper */
|
|
13
|
+
export class WebGPUVertexArray extends VertexArray {
|
|
14
|
+
override get [Symbol.toStringTag](): string {
|
|
15
|
+
return 'WebGPUVertexArray';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
readonly device: WebGPUDevice;
|
|
19
|
+
/** Vertex Array is a helper class under WebGPU */
|
|
20
|
+
readonly handle: never;
|
|
21
|
+
|
|
22
|
+
/** * Attribute 0 can not be disable on most desktop OpenGL based browsers */
|
|
23
|
+
static isConstantAttributeZeroSupported(device: Device): boolean {
|
|
24
|
+
return device.info.type === 'webgl2' || getBrowser() === 'Chrome';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Create a VertexArray
|
|
28
|
+
constructor(device: WebGPUDevice, props?: VertexArrayProps) {
|
|
29
|
+
super(device, props);
|
|
30
|
+
this.device = device;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override destroy(): void {}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Set an elements buffer, for indexed rendering.
|
|
37
|
+
* Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
|
|
38
|
+
*/
|
|
39
|
+
setIndexBuffer(buffer: Buffer | null): void {
|
|
40
|
+
// assert(!elementBuffer || elementBuffer.glTarget === GL.ELEMENT_ARRAY_BUFFER, ERR_ELEMENTS);
|
|
41
|
+
this.indexBuffer = buffer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
|
|
45
|
+
setBuffer(location: number, buffer: Buffer): void {
|
|
46
|
+
// Sanity check target
|
|
47
|
+
// if (buffer.glUsage === GL.ELEMENT_ARRAY_BUFFER) {
|
|
48
|
+
// throw new Error('Use setIndexBuffer');
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
this.attributes[location] = buffer;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Set a location in vertex attributes array to a constant value, disables the location */
|
|
55
|
+
override setConstant(location: number, value: TypedArray): void {
|
|
56
|
+
log.warn(`${this.id} constant attributes not supported on WebGPU`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override bindBeforeRender(renderPass: RenderPass, firstIndex?: number, indexCount?: number): void {
|
|
60
|
+
const webgpuRenderPass = renderPass as WebGPURenderPass;
|
|
61
|
+
const webgpuIndexBuffer = this.indexBuffer as WebGPUBuffer;
|
|
62
|
+
webgpuRenderPass.handle.setIndexBuffer(webgpuIndexBuffer?.handle, webgpuIndexBuffer?.indexType);
|
|
63
|
+
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
64
|
+
const webgpuBuffer = this.attributes[location] as WebGPUBuffer;
|
|
65
|
+
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer.handle);
|
|
66
|
+
}
|
|
67
|
+
// TODO - emit warnings/errors/throw if constants have been set on this vertex array
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override unbindAfterRender(renderPass: RenderPass): void {
|
|
71
|
+
// On WebGPU we don't unbind
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
+
// / <reference types="@webgpu/types" />
|
|
1
2
|
import type {Texture, TextureFormat, CanvasContextProps} from '@luma.gl/core';
|
|
2
3
|
import {CanvasContext, log} from '@luma.gl/core';
|
|
3
4
|
import {getWebGPUTextureFormat} from './helpers/convert-texture-format';
|
|
4
5
|
import {WebGPUDevice} from './webgpu-device';
|
|
5
6
|
import {WebGPUFramebuffer} from './resources/webgpu-framebuffer';
|
|
7
|
+
import {WebGPUTexture} from './resources/webgpu-texture';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
|
-
* Holds a WebGPU Canvas Context
|
|
10
|
+
* Holds a WebGPU Canvas Context
|
|
11
|
+
* The primary job of the CanvasContext is to generate textures for rendering into the current canvas
|
|
12
|
+
* It also manages canvas sizing calculations and resizing.
|
|
9
13
|
*/
|
|
10
14
|
export class WebGPUCanvasContext extends CanvasContext {
|
|
11
15
|
readonly device: WebGPUDevice;
|
|
12
16
|
readonly gpuCanvasContext: GPUCanvasContext;
|
|
13
|
-
|
|
17
|
+
/** Format of returned textures: "bgra8unorm", "rgba8unorm", "rgba16float". */
|
|
18
|
+
readonly format: TextureFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
19
|
+
/** Default stencil format for depth textures */
|
|
14
20
|
depthStencilFormat: TextureFormat = 'depth24plus';
|
|
15
|
-
sampleCount: number = 1;
|
|
16
21
|
|
|
17
22
|
private depthStencilAttachment: Texture | null = null;
|
|
18
23
|
|
|
@@ -22,31 +27,46 @@ export class WebGPUCanvasContext extends CanvasContext {
|
|
|
22
27
|
// TODO - hack to trigger resize?
|
|
23
28
|
this.width = -1;
|
|
24
29
|
this.height = -1;
|
|
25
|
-
|
|
30
|
+
|
|
26
31
|
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
27
32
|
// @ts-ignore TODO - we don't handle OffscreenRenderingContext.
|
|
28
|
-
this.gpuCanvasContext = this.canvas.getContext('webgpu')
|
|
29
|
-
//
|
|
30
|
-
this.format = this.gpuCanvasContext.getPreferredFormat(adapter);
|
|
33
|
+
this.gpuCanvasContext = this.canvas.getContext('webgpu');
|
|
34
|
+
// TODO this has been replaced
|
|
35
|
+
// this.format = this.gpuCanvasContext.getPreferredFormat(adapter);
|
|
36
|
+
this.format = 'bgra8unorm';
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
33
40
|
destroy(): void {
|
|
34
41
|
this.gpuCanvasContext.unconfigure();
|
|
35
42
|
}
|
|
36
43
|
|
|
44
|
+
getCurrentTexture(): WebGPUTexture {
|
|
45
|
+
// Wrap the current canvas context texture in a luma.gl texture
|
|
46
|
+
return this.device._createTexture({
|
|
47
|
+
id: 'default-render-target',
|
|
48
|
+
handle: this.gpuCanvasContext.getCurrentTexture()
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
37
52
|
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
38
53
|
getCurrentFramebuffer(): WebGPUFramebuffer {
|
|
39
54
|
// Ensure the canvas context size is updated
|
|
40
55
|
this.update();
|
|
41
56
|
|
|
57
|
+
// Wrap the current canvas context texture in a luma.gl texture
|
|
58
|
+
// const currentColorAttachment = this.device.createTexture({
|
|
59
|
+
// id: 'default-render-target',
|
|
60
|
+
// handle: this.gpuCanvasContext.getCurrentTexture(),
|
|
61
|
+
// format: this.format,
|
|
62
|
+
// width: this.width,
|
|
63
|
+
// height: this.height
|
|
64
|
+
// });
|
|
65
|
+
|
|
42
66
|
// Wrap the current canvas context texture in a luma.gl texture
|
|
43
|
-
const currentColorAttachment = this.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
format: this.format,
|
|
47
|
-
width: this.width,
|
|
48
|
-
height: this.height
|
|
49
|
-
});
|
|
67
|
+
const currentColorAttachment = this.getCurrentTexture();
|
|
68
|
+
this.width = currentColorAttachment.width;
|
|
69
|
+
this.height = currentColorAttachment.height;
|
|
50
70
|
|
|
51
71
|
// Resize the depth stencil attachment
|
|
52
72
|
this._createDepthStencilAttachment();
|
|
@@ -77,14 +97,14 @@ export class WebGPUCanvasContext extends CanvasContext {
|
|
|
77
97
|
this.gpuCanvasContext.configure({
|
|
78
98
|
device: this.device.handle,
|
|
79
99
|
format: getWebGPUTextureFormat(this.format),
|
|
80
|
-
//
|
|
100
|
+
// Can be used to define e.g. -srgb views
|
|
101
|
+
// viewFormats: [...]
|
|
81
102
|
colorSpace: this.props.colorSpace,
|
|
82
103
|
alphaMode: this.props.alphaMode
|
|
83
104
|
});
|
|
84
105
|
|
|
85
106
|
log.log(1, `Resized to ${this.width}x${this.height}px`)();
|
|
86
107
|
}
|
|
87
|
-
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
resize(options?: {width?: number; height?: number; useDevicePixels?: boolean | number}): void {
|
|
@@ -19,7 +19,8 @@ import type {
|
|
|
19
19
|
ComputePipelineProps,
|
|
20
20
|
RenderPassProps,
|
|
21
21
|
ComputePassProps,
|
|
22
|
-
// CommandEncoderProps
|
|
22
|
+
// CommandEncoderProps,
|
|
23
|
+
VertexArrayProps
|
|
23
24
|
} from '@luma.gl/core';
|
|
24
25
|
import {Device, CanvasContext, log, uid} from '@luma.gl/core';
|
|
25
26
|
import {WebGPUBuffer} from './resources/webgpu-buffer';
|
|
@@ -33,6 +34,7 @@ import {WebGPUComputePipeline} from './resources/webgpu-compute-pipeline';
|
|
|
33
34
|
import {WebGPURenderPass} from './resources/webgpu-render-pass';
|
|
34
35
|
import {WebGPUComputePass} from './resources/webgpu-compute-pass';
|
|
35
36
|
// import {WebGPUCommandEncoder} from './resources/webgpu-command-encoder';
|
|
37
|
+
import {WebGPUVertexArray} from './resources/webgpu-vertex-array';
|
|
36
38
|
|
|
37
39
|
import {WebGPUCanvasContext} from './webgpu-canvas-context';
|
|
38
40
|
// import {loadGlslangModule} from '../glsl/glslang';
|
|
@@ -105,7 +107,7 @@ export class WebGPUDevice extends Device {
|
|
|
105
107
|
renderer: '',
|
|
106
108
|
version: '',
|
|
107
109
|
gpu: 'unknown', // 'nvidia' | 'amd' | 'intel' | 'apple' | 'unknown',
|
|
108
|
-
shadingLanguages: ['
|
|
110
|
+
shadingLanguages: ['wgsl'],
|
|
109
111
|
shadingLanguageVersions: {
|
|
110
112
|
glsl: '450',
|
|
111
113
|
wgsl: '100'
|
|
@@ -122,9 +124,9 @@ export class WebGPUDevice extends Device {
|
|
|
122
124
|
});
|
|
123
125
|
|
|
124
126
|
// Note: WebGPU devices can be created without a canvas, for compute shader purposes
|
|
125
|
-
if (props.canvas) {
|
|
126
|
-
|
|
127
|
-
}
|
|
127
|
+
// if (props.canvas) {
|
|
128
|
+
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, {canvas: props.canvas});
|
|
129
|
+
// }
|
|
128
130
|
|
|
129
131
|
this.features = this._getFeatures();
|
|
130
132
|
}
|
|
@@ -199,6 +201,10 @@ export class WebGPUDevice extends Device {
|
|
|
199
201
|
return new WebGPUComputePipeline(this, props);
|
|
200
202
|
}
|
|
201
203
|
|
|
204
|
+
createVertexArray(props: VertexArrayProps): WebGPUVertexArray {
|
|
205
|
+
return new WebGPUVertexArray(this, props);
|
|
206
|
+
}
|
|
207
|
+
|
|
202
208
|
// WebGPU specifics
|
|
203
209
|
|
|
204
210
|
/**
|
|
@@ -227,24 +233,26 @@ export class WebGPUDevice extends Device {
|
|
|
227
233
|
* Gets default renderpass encoder.
|
|
228
234
|
* Creates a new encoder against default canvasContext if not already created
|
|
229
235
|
* @note Called internally by Model.
|
|
236
|
+
* @deprecated Create explicit pass with device.beginRenderPass
|
|
230
237
|
*/
|
|
231
238
|
getDefaultRenderPass(): WebGPURenderPass {
|
|
232
|
-
this.renderPass =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return this.renderPass;
|
|
239
|
+
// this.renderPass =
|
|
240
|
+
// this.renderPass ||
|
|
241
|
+
// this.beginRenderPass({
|
|
242
|
+
// framebuffer: this.canvasContext?.getCurrentFramebuffer()
|
|
243
|
+
// });
|
|
244
|
+
// return this.renderPass;
|
|
245
|
+
throw new Error('a');
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
submit(): void {
|
|
241
|
-
this.renderPass?.end();
|
|
249
|
+
// this.renderPass?.end();
|
|
242
250
|
const commandBuffer = this.commandEncoder?.finish();
|
|
243
251
|
if (commandBuffer) {
|
|
244
252
|
this.handle.queue.submit([commandBuffer]);
|
|
245
253
|
}
|
|
246
254
|
this.commandEncoder = null;
|
|
247
|
-
this.renderPass = null;
|
|
255
|
+
// this.renderPass = null;
|
|
248
256
|
}
|
|
249
257
|
|
|
250
258
|
_getFeatures() {
|