@luma.gl/webgpu 9.1.9 → 9.2.0-alpha.2
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/accessor-to-format.js +1 -0
- package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
- package/dist/adapter/helpers/get-bind-group.d.ts +3 -1
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +28 -10
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +5 -5
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +89 -75
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +13 -16
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +132 -93
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.d.ts +10 -0
- package/dist/adapter/resources/webgpu-command-buffer.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-command-buffer.js +18 -0
- package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -0
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +12 -5
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +28 -5
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +2 -2
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.d.ts +2 -2
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +3 -2
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +1 -0
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts +2 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +5 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +11 -6
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +5 -4
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +33 -20
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +1 -1
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +7 -8
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.js +15 -10
- package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +4 -37
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +97 -126
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.d.ts +2 -2
- package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js +2 -2
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
- package/dist/adapter/webgpu-adapter.d.ts +2 -3
- package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
- package/dist/adapter/webgpu-adapter.js +54 -43
- package/dist/adapter/webgpu-adapter.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +7 -15
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +50 -72
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +16 -27
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +48 -65
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/dist.dev.js +1919 -1520
- package/dist/dist.min.js +6 -5
- package/dist/index.cjs +1749 -1397
- package/dist/index.cjs.map +4 -4
- package/package.json +3 -3
- package/src/adapter/helpers/get-bind-group.ts +31 -11
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +5 -5
- package/src/adapter/helpers/webgpu-parameters.ts +114 -102
- package/src/adapter/resources/webgpu-buffer.ts +163 -102
- package/src/adapter/resources/webgpu-command-buffer.ts +24 -0
- package/src/adapter/resources/webgpu-command-encoder.ts +34 -4
- package/src/adapter/resources/webgpu-compute-pass.ts +1 -1
- package/src/adapter/resources/webgpu-compute-pipeline.ts +2 -2
- package/src/adapter/resources/webgpu-external-texture.ts +2 -2
- package/src/adapter/resources/webgpu-framebuffer.ts +3 -2
- package/src/adapter/resources/webgpu-pipeline-layout.ts +8 -3
- package/src/adapter/resources/webgpu-render-pass.ts +11 -6
- package/src/adapter/resources/webgpu-render-pipeline.ts +39 -24
- package/src/adapter/resources/webgpu-sampler.ts +1 -1
- package/src/adapter/resources/webgpu-shader.ts +11 -8
- package/src/adapter/resources/webgpu-texture-view.ts +14 -8
- package/src/adapter/resources/webgpu-texture.ts +106 -186
- package/src/adapter/resources/webgpu-vertex-array.ts +2 -2
- package/src/adapter/webgpu-adapter.ts +72 -58
- package/src/adapter/webgpu-canvas-context.ts +62 -82
- package/src/adapter/webgpu-device.ts +66 -105
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {ShaderProps, CompilerMessage} from '@luma.gl/core';
|
|
6
|
-
import {Shader
|
|
6
|
+
import {Shader} from '@luma.gl/core';
|
|
7
7
|
import type {WebGPUDevice} from '../webgpu-device';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -22,12 +22,15 @@ export class WebGPUShader extends Shader {
|
|
|
22
22
|
throw new Error('GLSL shaders are not supported in WebGPU');
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
this.device.
|
|
25
|
+
this.device.pushErrorScope('validation');
|
|
26
26
|
this.handle = this.props.handle || this.device.handle.createShaderModule({code: props.source});
|
|
27
|
-
this.device.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
28
|
+
this.device.reportError(
|
|
29
|
+
new Error(`${this} creation failed:\n"${error.message}"`),
|
|
30
|
+
this,
|
|
31
|
+
this.props.source
|
|
32
|
+
)();
|
|
33
|
+
this.device.debug();
|
|
31
34
|
});
|
|
32
35
|
|
|
33
36
|
this.handle.label = this.props.id;
|
|
@@ -45,10 +48,10 @@ export class WebGPUShader extends Shader {
|
|
|
45
48
|
this.debugShader();
|
|
46
49
|
|
|
47
50
|
if (this.compilationStatus === 'error') {
|
|
48
|
-
log.error(`Shader compilation error`, shaderLog)();
|
|
49
51
|
// Note: Even though this error is asynchronous and thrown after the constructor completes,
|
|
50
52
|
// it will result in a useful stack trace leading back to the constructor
|
|
51
|
-
|
|
53
|
+
this.device.reportError(new Error(`Shader compilation error`), this, shaderLog)();
|
|
54
|
+
this.device.debug();
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
@@ -38,17 +38,23 @@ export class WebGPUTextureView extends TextureView {
|
|
|
38
38
|
this.device = device;
|
|
39
39
|
this.texture = props.texture;
|
|
40
40
|
|
|
41
|
+
this.device.pushErrorScope('validation');
|
|
41
42
|
this.handle =
|
|
42
|
-
|
|
43
|
+
// props.handle ||
|
|
43
44
|
this.texture.handle.createView({
|
|
44
|
-
format: (props.format || this.texture.format) as GPUTextureFormat,
|
|
45
|
-
dimension: props.dimension || this.texture.dimension,
|
|
46
|
-
aspect: props.aspect,
|
|
47
|
-
baseMipLevel: props.baseMipLevel,
|
|
48
|
-
mipLevelCount: props.mipLevelCount,
|
|
49
|
-
baseArrayLayer: props.baseArrayLayer,
|
|
50
|
-
arrayLayerCount: props.arrayLayerCount
|
|
45
|
+
format: (this.props.format || this.texture.format) as GPUTextureFormat,
|
|
46
|
+
dimension: this.props.dimension || this.texture.dimension,
|
|
47
|
+
aspect: this.props.aspect,
|
|
48
|
+
baseMipLevel: this.props.baseMipLevel,
|
|
49
|
+
mipLevelCount: this.props.mipLevelCount,
|
|
50
|
+
baseArrayLayer: this.props.baseArrayLayer,
|
|
51
|
+
arrayLayerCount: this.props.arrayLayerCount
|
|
51
52
|
});
|
|
53
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
54
|
+
this.device.reportError(new Error(`TextureView constructor: ${error.message}`), this)();
|
|
55
|
+
this.device.debug();
|
|
56
|
+
});
|
|
57
|
+
|
|
52
58
|
this.handle.label = this.props.id;
|
|
53
59
|
}
|
|
54
60
|
|
|
@@ -1,42 +1,21 @@
|
|
|
1
1
|
// luma.gl, MIT license
|
|
2
2
|
import type {
|
|
3
|
-
// Device,
|
|
4
3
|
TextureProps,
|
|
5
4
|
TextureViewProps,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// TextureCubeFace,
|
|
10
|
-
// ExternalImage,
|
|
11
|
-
// TextureLevelData,
|
|
12
|
-
Texture1DData,
|
|
13
|
-
Texture2DData,
|
|
14
|
-
Texture3DData,
|
|
15
|
-
TextureCubeData,
|
|
16
|
-
TextureArrayData,
|
|
17
|
-
TextureCubeArrayData,
|
|
18
|
-
ExternalImage
|
|
5
|
+
CopyExternalImageOptions,
|
|
6
|
+
CopyImageDataOptions,
|
|
7
|
+
SamplerProps
|
|
19
8
|
} from '@luma.gl/core';
|
|
20
|
-
import {Texture} from '@luma.gl/core';
|
|
9
|
+
import {Texture, log} from '@luma.gl/core';
|
|
21
10
|
|
|
22
11
|
import {getWebGPUTextureFormat} from '../helpers/convert-texture-format';
|
|
23
12
|
import type {WebGPUDevice} from '../webgpu-device';
|
|
24
13
|
import {WebGPUSampler} from './webgpu-sampler';
|
|
25
14
|
import {WebGPUTextureView} from './webgpu-texture-view';
|
|
26
15
|
|
|
27
|
-
const BASE_DIMENSIONS: Record<string, '1d' | '2d' | '3d'> = {
|
|
28
|
-
'1d': '1d',
|
|
29
|
-
'2d': '2d',
|
|
30
|
-
'2d-array': '2d',
|
|
31
|
-
cube: '2d',
|
|
32
|
-
'cube-array': '2d',
|
|
33
|
-
'3d': '3d'
|
|
34
|
-
};
|
|
35
|
-
|
|
36
16
|
export class WebGPUTexture extends Texture {
|
|
37
17
|
readonly device: WebGPUDevice;
|
|
38
18
|
readonly handle: GPUTexture;
|
|
39
|
-
|
|
40
19
|
sampler: WebGPUSampler;
|
|
41
20
|
view: WebGPUTextureView;
|
|
42
21
|
|
|
@@ -44,197 +23,138 @@ export class WebGPUTexture extends Texture {
|
|
|
44
23
|
super(device, props);
|
|
45
24
|
this.device = device;
|
|
46
25
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (props.data) {
|
|
50
|
-
propsWithData.data = props.data;
|
|
26
|
+
if (this.dimension === 'cube') {
|
|
27
|
+
this.depth = 6;
|
|
51
28
|
}
|
|
52
29
|
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
30
|
+
this.device.pushErrorScope('out-of-memory');
|
|
31
|
+
this.device.pushErrorScope('validation');
|
|
32
|
+
|
|
33
|
+
this.handle =
|
|
34
|
+
this.props.handle ||
|
|
35
|
+
this.device.handle.createTexture({
|
|
36
|
+
label: this.id,
|
|
37
|
+
size: {
|
|
38
|
+
width: this.width,
|
|
39
|
+
height: this.height,
|
|
40
|
+
depthOrArrayLayers: this.depth
|
|
41
|
+
},
|
|
42
|
+
usage: this.props.usage || Texture.TEXTURE | Texture.COPY_DST,
|
|
43
|
+
dimension: this.baseDimension,
|
|
44
|
+
format: getWebGPUTextureFormat(this.format),
|
|
45
|
+
mipLevelCount: this.mipLevels,
|
|
46
|
+
sampleCount: this.props.samples
|
|
47
|
+
});
|
|
48
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
49
|
+
this.device.reportError(new Error(`${this} constructor: ${error.message}`), this)();
|
|
50
|
+
this.device.debug();
|
|
51
|
+
});
|
|
52
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
53
|
+
this.device.reportError(new Error(`${this} out of memory: ${error.message}`), this)();
|
|
54
|
+
this.device.debug();
|
|
55
|
+
});
|
|
70
56
|
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
// Update props if external handle was supplied - used mainly by CanvasContext.getDefaultFramebuffer()
|
|
58
|
+
// TODO - Read all properties directly from the supplied handle?
|
|
59
|
+
if (this.props.handle) {
|
|
60
|
+
this.handle.label ||= this.id;
|
|
61
|
+
this.width = this.handle.width;
|
|
62
|
+
this.height = this.handle.height;
|
|
77
63
|
}
|
|
78
64
|
|
|
79
|
-
this.width = this.handle.width;
|
|
80
|
-
this.height = this.handle.height;
|
|
81
|
-
// Why not just read all properties directly from the texture
|
|
82
|
-
// this.depthOrArrayLayers = this.handle.depthOrArrayLayers;
|
|
83
|
-
// this.mipLevelCount = this.handle.mipLevelCount;
|
|
84
|
-
// this.sampleCount = this.handle.sampleCount;
|
|
85
|
-
// this.dimension = this.handle.dimension;
|
|
86
|
-
// this.format = this.handle.format;
|
|
87
|
-
// this.usage = this.handle.usage;
|
|
88
|
-
|
|
89
|
-
// Create a default sampler. This mimics the WebGL1 API where sampler props are stored on the texture
|
|
90
|
-
// this.setSampler(props.sampler);
|
|
91
65
|
this.sampler =
|
|
92
66
|
props.sampler instanceof WebGPUSampler
|
|
93
67
|
? props.sampler
|
|
94
|
-
: new WebGPUSampler(this.device, props.sampler || {});
|
|
95
|
-
|
|
96
|
-
// TODO - To support texture arrays we need to create custom views...
|
|
97
|
-
// But we are not ready to expose TextureViews to the public API.
|
|
98
|
-
// @ts-expect-error
|
|
68
|
+
: new WebGPUSampler(this.device, (props.sampler as SamplerProps) || {});
|
|
99
69
|
|
|
100
|
-
this.view = new WebGPUTextureView(this.device, {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// aspect = "all";
|
|
104
|
-
// baseMipLevel: 0;
|
|
105
|
-
// mipLevelCount;
|
|
106
|
-
// baseArrayLayer = 0;
|
|
107
|
-
// arrayLayerCount;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
protected createHandle(): GPUTexture {
|
|
111
|
-
// Deduce size from data - TODO this is a hack
|
|
112
|
-
// @ts-expect-error
|
|
113
|
-
const width = this.props.width || this.props.data?.width || 1;
|
|
114
|
-
// @ts-expect-error
|
|
115
|
-
const height = this.props.height || this.props.data?.height || 1;
|
|
116
|
-
|
|
117
|
-
return this.device.handle.createTexture({
|
|
118
|
-
label: this.id,
|
|
119
|
-
size: {
|
|
120
|
-
width,
|
|
121
|
-
height,
|
|
122
|
-
depthOrArrayLayers: this.depth
|
|
123
|
-
},
|
|
124
|
-
usage: this.props.usage || Texture.TEXTURE | Texture.COPY_DST,
|
|
125
|
-
dimension: BASE_DIMENSIONS[this.dimension],
|
|
126
|
-
format: getWebGPUTextureFormat(this.format),
|
|
70
|
+
this.view = new WebGPUTextureView(this.device, {
|
|
71
|
+
...this.props,
|
|
72
|
+
texture: this,
|
|
127
73
|
mipLevelCount: this.mipLevels,
|
|
128
|
-
|
|
74
|
+
// Note: arrayLayerCount controls the view of array textures, but does not apply to 3d texture depths
|
|
75
|
+
arrayLayerCount: this.dimension !== '3d' ? this.depth : 1
|
|
129
76
|
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** @deprecated - intention is to use the createView public API */
|
|
133
|
-
createGPUTextureView(): GPUTextureView {
|
|
134
|
-
return this.handle.createView({label: this.id});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Set default sampler
|
|
139
|
-
* Accept a sampler instance or set of props;
|
|
140
|
-
*/
|
|
141
|
-
setSampler(sampler: Sampler | SamplerProps): this {
|
|
142
|
-
this.sampler =
|
|
143
|
-
sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
144
|
-
return this;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
setTexture1DData(data: Texture1DData): void {
|
|
148
|
-
throw new Error('not implemented');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
setTexture2DData(lodData: Texture2DData, depth?: number, target?: number): void {
|
|
152
|
-
throw new Error('not implemented');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
setTexture3DData(lodData: Texture3DData, depth?: number, target?: number): void {
|
|
156
|
-
throw new Error('not implemented');
|
|
157
|
-
}
|
|
158
77
|
|
|
159
|
-
|
|
160
|
-
|
|
78
|
+
// Set initial data
|
|
79
|
+
// Texture base class strips out the data prop from this.props, so we need to handle it here
|
|
80
|
+
this._initializeData(props.data);
|
|
161
81
|
}
|
|
162
82
|
|
|
163
|
-
|
|
164
|
-
|
|
83
|
+
override destroy(): void {
|
|
84
|
+
this.handle?.destroy();
|
|
85
|
+
// @ts-expect-error readonly
|
|
86
|
+
this.handle = null;
|
|
165
87
|
}
|
|
166
88
|
|
|
167
|
-
|
|
168
|
-
|
|
89
|
+
createView(props: TextureViewProps): WebGPUTextureView {
|
|
90
|
+
return new WebGPUTextureView(this.device, {...props, texture: this});
|
|
169
91
|
}
|
|
170
92
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
93
|
+
copyImageData(options_: CopyImageDataOptions): void {
|
|
94
|
+
const {width, height, depth} = this;
|
|
95
|
+
const options = this._normalizeCopyImageDataOptions(options_);
|
|
96
|
+
this.device.pushErrorScope('validation');
|
|
97
|
+
this.device.handle.queue.writeTexture(
|
|
98
|
+
// destination: GPUImageCopyTexture
|
|
99
|
+
{
|
|
100
|
+
// texture subresource
|
|
101
|
+
texture: this.handle,
|
|
102
|
+
mipLevel: options.mipLevel,
|
|
103
|
+
aspect: options.aspect,
|
|
104
|
+
// origin to write to
|
|
105
|
+
origin: [options.x, options.y, options.z]
|
|
106
|
+
},
|
|
107
|
+
// data
|
|
108
|
+
options.data,
|
|
109
|
+
// dataLayout: GPUImageDataLayout
|
|
110
|
+
{
|
|
111
|
+
offset: options.byteOffset,
|
|
112
|
+
bytesPerRow: options.bytesPerRow,
|
|
113
|
+
rowsPerImage: options.rowsPerImage
|
|
114
|
+
},
|
|
115
|
+
// size: GPUExtent3D - extents of the content to write
|
|
116
|
+
[width, height, depth]
|
|
117
|
+
);
|
|
118
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
119
|
+
this.device.reportError(new Error(`copyImageData: ${error.message}`), this)();
|
|
120
|
+
this.device.debug();
|
|
121
|
+
});
|
|
180
122
|
}
|
|
181
123
|
|
|
182
|
-
copyExternalImage(
|
|
183
|
-
|
|
184
|
-
width?: number;
|
|
185
|
-
height?: number;
|
|
186
|
-
depth?: number;
|
|
187
|
-
sourceX?: number;
|
|
188
|
-
sourceY?: number;
|
|
189
|
-
mipLevel?: number;
|
|
190
|
-
x?: number;
|
|
191
|
-
y?: number;
|
|
192
|
-
z?: number;
|
|
193
|
-
aspect?: 'all' | 'stencil-only' | 'depth-only';
|
|
194
|
-
colorSpace?: 'srgb';
|
|
195
|
-
premultipliedAlpha?: boolean;
|
|
196
|
-
}): {width: number; height: number} {
|
|
197
|
-
const size = Texture.getExternalImageSize(options.image);
|
|
198
|
-
const opts = {...Texture.defaultCopyExternalImageOptions, ...size, ...options};
|
|
199
|
-
const {
|
|
200
|
-
image,
|
|
201
|
-
sourceX,
|
|
202
|
-
sourceY,
|
|
203
|
-
width,
|
|
204
|
-
height,
|
|
205
|
-
depth,
|
|
206
|
-
mipLevel,
|
|
207
|
-
x,
|
|
208
|
-
y,
|
|
209
|
-
z,
|
|
210
|
-
aspect,
|
|
211
|
-
colorSpace,
|
|
212
|
-
premultipliedAlpha,
|
|
213
|
-
flipY
|
|
214
|
-
} = opts;
|
|
215
|
-
|
|
216
|
-
// TODO - max out width
|
|
124
|
+
copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
|
|
125
|
+
const options = this._normalizeCopyExternalImageOptions(options_);
|
|
217
126
|
|
|
127
|
+
this.device.pushErrorScope('validation');
|
|
218
128
|
this.device.handle.queue.copyExternalImageToTexture(
|
|
219
129
|
// source: GPUImageCopyExternalImage
|
|
220
130
|
{
|
|
221
|
-
source: image,
|
|
222
|
-
origin: [sourceX, sourceY],
|
|
223
|
-
flipY
|
|
131
|
+
source: options.image,
|
|
132
|
+
origin: [options.sourceX, options.sourceY],
|
|
133
|
+
flipY: options.flipY
|
|
224
134
|
},
|
|
225
135
|
// destination: GPUImageCopyTextureTagged
|
|
226
136
|
{
|
|
227
137
|
texture: this.handle,
|
|
228
|
-
origin: [x, y,
|
|
229
|
-
mipLevel,
|
|
230
|
-
aspect,
|
|
231
|
-
colorSpace,
|
|
232
|
-
premultipliedAlpha
|
|
138
|
+
origin: [options.x, options.y, 0], // options.depth],
|
|
139
|
+
mipLevel: options.mipLevel,
|
|
140
|
+
aspect: options.aspect,
|
|
141
|
+
colorSpace: options.colorSpace,
|
|
142
|
+
premultipliedAlpha: options.premultipliedAlpha
|
|
233
143
|
},
|
|
234
144
|
// copySize: GPUExtent3D
|
|
235
|
-
[width, height,
|
|
145
|
+
[options.width, options.height, 1]
|
|
236
146
|
);
|
|
237
|
-
|
|
147
|
+
this.device.popErrorScope((error: GPUError) => {
|
|
148
|
+
this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
|
|
149
|
+
this.device.debug();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// TODO - should these be clipped to the texture size minus x,y,z?
|
|
153
|
+
return {width: options.width, height: options.height};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
override generateMipmapsWebGL(): void {
|
|
157
|
+
log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
|
|
238
158
|
}
|
|
239
159
|
|
|
240
160
|
// WebGPU specific
|
|
@@ -256,7 +176,7 @@ export class WebGPUTexture extends Texture {
|
|
|
256
176
|
device.submit([encoder.finish()]);
|
|
257
177
|
|
|
258
178
|
// Get the data on the CPU.
|
|
259
|
-
await buffer.
|
|
179
|
+
await buffer.mapAndReadAsync(GPUMapMode.READ);
|
|
260
180
|
saveScreenshot(buffer.getMappedRange());
|
|
261
181
|
buffer.unmap();
|
|
262
182
|
}
|
|
@@ -18,8 +18,8 @@ export class WebGPUVertexArray extends VertexArray {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
readonly device: WebGPUDevice;
|
|
21
|
-
/** Vertex Array is a helper class under WebGPU */
|
|
22
|
-
readonly handle
|
|
21
|
+
/** Vertex Array is just a helper class under WebGPU */
|
|
22
|
+
readonly handle = null;
|
|
23
23
|
|
|
24
24
|
// Create a VertexArray
|
|
25
25
|
constructor(device: WebGPUDevice, props: VertexArrayProps) {
|
|
@@ -2,85 +2,99 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
import {WebGPUDevice} from './webgpu-device';
|
|
7
|
-
|
|
5
|
+
// prettier-ignore
|
|
8
6
|
// / <reference types="@webgpu/types" />
|
|
9
7
|
|
|
8
|
+
import {Adapter, DeviceProps, log} from '@luma.gl/core';
|
|
9
|
+
import type {WebGPUDevice} from './webgpu-device';
|
|
10
|
+
|
|
10
11
|
export class WebGPUAdapter extends Adapter {
|
|
11
12
|
/** type of device's created by this adapter */
|
|
12
13
|
readonly type: WebGPUDevice['type'] = 'webgpu';
|
|
13
14
|
|
|
14
|
-
constructor() {
|
|
15
|
-
super();
|
|
16
|
-
// @ts-ignore For backwards compatibility luma.registerDevices
|
|
17
|
-
WebGPUDevice.adapter = this;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Check if WebGPU is available */
|
|
21
15
|
isSupported(): boolean {
|
|
16
|
+
// Check if WebGPU is available
|
|
22
17
|
return Boolean(typeof navigator !== 'undefined' && navigator.gpu);
|
|
23
18
|
}
|
|
24
19
|
|
|
20
|
+
isDeviceHandle(handle: unknown): boolean {
|
|
21
|
+
if (typeof GPUDevice !== 'undefined' && handle instanceof GPUDevice) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// TODO - WebGPU does not yet seem to have a stable in-browser API, so we "sniff" for members instead
|
|
26
|
+
if ((handle as any)?.queue) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
async create(props: DeviceProps): Promise<WebGPUDevice> {
|
|
26
34
|
if (!navigator.gpu) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
'WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu'
|
|
29
|
-
);
|
|
35
|
+
throw new Error('WebGPU not available. Recent Chrome browsers should work.');
|
|
30
36
|
}
|
|
31
|
-
log.groupCollapsed(1, 'WebGPUDevice created')();
|
|
32
|
-
const adapter = await navigator.gpu.requestAdapter({
|
|
33
|
-
powerPreference: 'high-performance'
|
|
34
|
-
// forceSoftware: false
|
|
35
|
-
});
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
log.groupCollapsed(1, 'WebGPUDevice created')();
|
|
39
|
+
try {
|
|
40
|
+
const adapter = await navigator.gpu.requestAdapter({
|
|
41
|
+
powerPreference: 'high-performance'
|
|
42
|
+
// forceSoftware: false
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!adapter) {
|
|
46
|
+
throw new Error('Failed to request WebGPU adapter');
|
|
47
|
+
}
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
// Note: adapter.requestAdapterInfo() has been replaced with adapter.info. Fall back in case adapter.info is not available
|
|
50
|
+
const adapterInfo =
|
|
51
|
+
adapter.info ||
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
(await adapter.requestAdapterInfo?.());
|
|
54
|
+
log.probe(2, 'Adapter available', adapterInfo)();
|
|
55
|
+
|
|
56
|
+
const requiredFeatures: GPUFeatureName[] = [];
|
|
57
|
+
const requiredLimits: Record<string, number> = {};
|
|
58
|
+
|
|
59
|
+
if (props._requestMaxLimits) {
|
|
60
|
+
// Require all features
|
|
61
|
+
requiredFeatures.push(...(Array.from(adapter.features) as GPUFeatureName[]));
|
|
62
|
+
|
|
63
|
+
// Require all limits
|
|
64
|
+
// Filter out chrome specific keys (avoid crash)
|
|
65
|
+
const limits = Object.keys(adapter.limits).filter(
|
|
66
|
+
key => !['minSubgroupSize', 'maxSubgroupSize'].includes(key)
|
|
67
|
+
);
|
|
68
|
+
for (const key of limits) {
|
|
69
|
+
const limit = key as keyof GPUSupportedLimits;
|
|
70
|
+
const value = adapter.limits[limit];
|
|
71
|
+
if (typeof value === 'number') {
|
|
72
|
+
requiredLimits[limit] = value;
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
75
|
}
|
|
66
|
-
}
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
const gpuDevice = await adapter.requestDevice({
|
|
78
|
+
requiredFeatures,
|
|
79
|
+
requiredLimits
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
log.probe(1, 'GPUDevice available')();
|
|
72
83
|
|
|
73
|
-
|
|
84
|
+
const {WebGPUDevice} = await import('./webgpu-device');
|
|
74
85
|
|
|
75
|
-
|
|
86
|
+
const device = new WebGPUDevice(props, gpuDevice, adapter, adapterInfo);
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
log.probe(
|
|
89
|
+
1,
|
|
90
|
+
'Device created. For more info, set chrome://flags/#enable-webgpu-developer-features'
|
|
91
|
+
)();
|
|
92
|
+
log.table(1, device.info)();
|
|
93
|
+
|
|
94
|
+
return device;
|
|
95
|
+
} finally {
|
|
96
|
+
log.groupEnd(1)();
|
|
97
|
+
}
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
async attach(handle: GPUDevice): Promise<WebGPUDevice> {
|