@luma.gl/webgpu 9.0.0-alpha.2 → 9.0.0-alpha.21
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/LICENSE +32 -0
- package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
- package/dist/adapter/helpers/convert-texture-format.d.ts +1 -1
- package/dist/adapter/helpers/convert-texture-format.js +0 -1
- package/dist/adapter/helpers/convert-texture-format.js.map +1 -1
- package/dist/adapter/helpers/generate-mipmaps.d.ts +1 -1
- package/dist/adapter/helpers/generate-mipmaps.js +1 -8
- package/dist/adapter/helpers/generate-mipmaps.js.map +1 -1
- package/dist/adapter/helpers/get-bind-group.d.ts +1 -1
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +0 -9
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +3 -17
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +50 -47
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +3 -4
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +12 -26
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +3 -4
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +7 -24
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +5 -5
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +11 -23
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +3 -3
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +3 -7
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.d.ts +4 -4
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js +2 -9
- package/dist/adapter/resources/webgpu-external-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +5 -5
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +12 -30
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-query.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts +5 -5
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +17 -30
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +7 -4
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +25 -43
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.d.ts +3 -3
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +8 -7
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts +4 -4
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +2 -16
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +4 -4
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +4 -20
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +5 -7
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +10 -31
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +19 -19
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +42 -71
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/adapter/webgpu-types.js.map +1 -1
- package/dist/dist.dev.js +3060 -0
- package/dist/glsl/glsllang.js +0 -1
- package/dist/glsl/glsllang.js.map +1 -1
- package/dist/index.cjs +1442 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -7
- package/dist/index.js.map +1 -1
- package/dist.min.js +17 -0
- package/package.json +18 -9
- package/src/.DS_Store +0 -0
- package/src/adapter/.DS_Store +0 -0
- package/src/adapter/helpers/generate-mipmaps.ts +1 -1
- package/src/adapter/helpers/get-bind-group.ts +4 -4
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +3 -3
- package/src/adapter/helpers/webgpu-parameters.ts +55 -46
- package/src/adapter/resources/webgpu-buffer.ts +6 -10
- package/src/adapter/resources/webgpu-command-encoder.ts +22 -20
- package/src/adapter/resources/webgpu-compute-pass.ts +12 -12
- package/src/adapter/resources/webgpu-compute-pipeline.ts +5 -4
- package/src/adapter/resources/webgpu-external-texture.ts +4 -4
- package/src/adapter/resources/webgpu-framebuffer.ts +18 -18
- package/src/adapter/resources/webgpu-query.ts +2 -2
- package/src/adapter/resources/webgpu-render-pass.ts +15 -12
- package/src/adapter/resources/webgpu-render-pipeline.ts +32 -15
- package/src/adapter/resources/webgpu-sampler.ts +11 -4
- package/src/adapter/resources/webgpu-shader.ts +7 -5
- package/src/adapter/resources/webgpu-texture.ts +7 -6
- package/src/adapter/webgpu-canvas-context.ts +16 -12
- package/src/adapter/webgpu-device.ts +63 -50
- package/src/index.ts +6 -9
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/bundle.js +0 -5
- package/dist/bundle.js.map +0 -1
- package/dist/init.d.ts +0 -2
- package/dist/init.d.ts.map +0 -1
- package/dist/init.js +0 -4
- package/dist/init.js.map +0 -1
- package/src/bundle.ts +0 -4
- package/src/init.ts +0 -4
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1442 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
22
|
+
var __export = (target, all) => {
|
|
23
|
+
for (var name in all)
|
|
24
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
25
|
+
};
|
|
26
|
+
var __copyProps = (to, from, except, desc) => {
|
|
27
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
28
|
+
for (let key of __getOwnPropNames(from))
|
|
29
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
30
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
31
|
+
}
|
|
32
|
+
return to;
|
|
33
|
+
};
|
|
34
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
|
+
var __async = (__this, __arguments, generator) => {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
var fulfilled = (value) => {
|
|
38
|
+
try {
|
|
39
|
+
step(generator.next(value));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
reject(e);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var rejected = (value) => {
|
|
45
|
+
try {
|
|
46
|
+
step(generator.throw(value));
|
|
47
|
+
} catch (e) {
|
|
48
|
+
reject(e);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
52
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// src/index.ts
|
|
57
|
+
var src_exports = {};
|
|
58
|
+
__export(src_exports, {
|
|
59
|
+
WebGPUBuffer: () => WebGPUBuffer,
|
|
60
|
+
WebGPUDevice: () => WebGPUDevice,
|
|
61
|
+
WebGPUSampler: () => WebGPUSampler,
|
|
62
|
+
WebGPUShader: () => WebGPUShader,
|
|
63
|
+
WebGPUTexture: () => WebGPUTexture
|
|
64
|
+
});
|
|
65
|
+
module.exports = __toCommonJS(src_exports);
|
|
66
|
+
|
|
67
|
+
// src/adapter/webgpu-device.ts
|
|
68
|
+
var import_api14 = require("@luma.gl/api");
|
|
69
|
+
|
|
70
|
+
// src/adapter/resources/webgpu-buffer.ts
|
|
71
|
+
var import_api = require("@luma.gl/api");
|
|
72
|
+
function getByteLength(props) {
|
|
73
|
+
var _a;
|
|
74
|
+
return props.byteLength || ((_a = props.data) == null ? void 0 : _a.byteLength) || 0;
|
|
75
|
+
}
|
|
76
|
+
var WebGPUBuffer = class extends import_api.Buffer {
|
|
77
|
+
constructor(device, props) {
|
|
78
|
+
super(device, props);
|
|
79
|
+
this.device = device;
|
|
80
|
+
this.byteLength = getByteLength(props);
|
|
81
|
+
const mapBuffer = Boolean(props.data);
|
|
82
|
+
this.handle = this.props.handle || this.device.handle.createBuffer({
|
|
83
|
+
size: this.byteLength,
|
|
84
|
+
// usage defaults to vertex
|
|
85
|
+
usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
86
|
+
mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
|
|
87
|
+
label: this.props.id
|
|
88
|
+
});
|
|
89
|
+
if (props.data) {
|
|
90
|
+
this._writeMapped(props.data);
|
|
91
|
+
}
|
|
92
|
+
if (mapBuffer && !props.mappedAtCreation) {
|
|
93
|
+
this.handle.unmap();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
destroy() {
|
|
97
|
+
this.handle.destroy();
|
|
98
|
+
}
|
|
99
|
+
// WebGPU provides multiple ways to write a buffer...
|
|
100
|
+
write(data, byteOffset = 0) {
|
|
101
|
+
this.device.handle.queue.writeBuffer(
|
|
102
|
+
this.handle,
|
|
103
|
+
byteOffset,
|
|
104
|
+
data.buffer,
|
|
105
|
+
data.byteOffset,
|
|
106
|
+
data.byteLength
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
readAsync() {
|
|
110
|
+
return __async(this, arguments, function* (byteOffset = 0, byteLength = this.byteLength) {
|
|
111
|
+
const tempBuffer = new WebGPUBuffer(this.device, { usage: import_api.Buffer.MAP_READ | import_api.Buffer.COPY_DST, byteLength });
|
|
112
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
113
|
+
commandEncoder.copyBufferToBuffer(this.handle, byteOffset, tempBuffer.handle, 0, byteLength);
|
|
114
|
+
this.device.handle.queue.submit([commandEncoder.finish()]);
|
|
115
|
+
yield tempBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
|
|
116
|
+
const arrayBuffer = tempBuffer.handle.getMappedRange().slice(0);
|
|
117
|
+
tempBuffer.handle.unmap();
|
|
118
|
+
tempBuffer.destroy();
|
|
119
|
+
return arrayBuffer;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
_writeMapped(typedArray) {
|
|
123
|
+
const arrayBuffer = this.handle.getMappedRange();
|
|
124
|
+
new typedArray.constructor(arrayBuffer).set(typedArray);
|
|
125
|
+
}
|
|
126
|
+
// WEBGPU API
|
|
127
|
+
mapAsync(mode, offset = 0, size) {
|
|
128
|
+
return this.handle.mapAsync(mode, offset, size);
|
|
129
|
+
}
|
|
130
|
+
getMappedRange(offset = 0, size) {
|
|
131
|
+
return this.handle.getMappedRange(offset, size);
|
|
132
|
+
}
|
|
133
|
+
unmap() {
|
|
134
|
+
this.handle.unmap();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/adapter/resources/webgpu-texture.ts
|
|
139
|
+
var import_api3 = require("@luma.gl/api");
|
|
140
|
+
|
|
141
|
+
// src/adapter/helpers/convert-texture-format.ts
|
|
142
|
+
function getWebGPUTextureFormat(format) {
|
|
143
|
+
if (format.includes("webgl")) {
|
|
144
|
+
throw new Error("webgl-only format");
|
|
145
|
+
}
|
|
146
|
+
return format;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/adapter/resources/webgpu-sampler.ts
|
|
150
|
+
var import_api2 = require("@luma.gl/api");
|
|
151
|
+
var WebGPUSampler = class extends import_api2.Sampler {
|
|
152
|
+
constructor(device, props) {
|
|
153
|
+
super(device, props);
|
|
154
|
+
this.device = device;
|
|
155
|
+
const samplerProps = __spreadValues({}, this.props);
|
|
156
|
+
if (samplerProps.type !== "comparison-sampler") {
|
|
157
|
+
delete samplerProps.compare;
|
|
158
|
+
}
|
|
159
|
+
this.handle = this.handle || this.device.handle.createSampler(samplerProps);
|
|
160
|
+
this.handle.label = this.props.id;
|
|
161
|
+
}
|
|
162
|
+
destroy() {
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/adapter/resources/webgpu-texture.ts
|
|
167
|
+
var BASE_DIMENSIONS = {
|
|
168
|
+
"1d": "1d",
|
|
169
|
+
"2d": "2d",
|
|
170
|
+
"2d-array": "2d",
|
|
171
|
+
"cube": "2d",
|
|
172
|
+
"cube-array": "2d",
|
|
173
|
+
"3d": "3d"
|
|
174
|
+
};
|
|
175
|
+
var WebGPUTexture = class extends import_api3.Texture {
|
|
176
|
+
// static async createFromImageURL(src, usage = 0) {
|
|
177
|
+
// const img = document.createElement('img');
|
|
178
|
+
// img.src = src;
|
|
179
|
+
// await img.decode();
|
|
180
|
+
// return WebGPUTexture(img, usage);
|
|
181
|
+
// }
|
|
182
|
+
constructor(device, props) {
|
|
183
|
+
super(device, props);
|
|
184
|
+
if (typeof this.props.format === "number") {
|
|
185
|
+
throw new Error("number format");
|
|
186
|
+
}
|
|
187
|
+
this.device = device;
|
|
188
|
+
this.handle = this.props.handle || this.createHandle();
|
|
189
|
+
if (this.props.data) {
|
|
190
|
+
this.setData({ data: this.props.data });
|
|
191
|
+
}
|
|
192
|
+
this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler);
|
|
193
|
+
this.view = this.handle.createView({
|
|
194
|
+
// format: this.props.format,
|
|
195
|
+
// dimension: this.props.dimension,
|
|
196
|
+
// aspect = "all";
|
|
197
|
+
// baseMipLevel: 0;
|
|
198
|
+
// mipLevelCount;
|
|
199
|
+
// baseArrayLayer = 0;
|
|
200
|
+
// arrayLayerCount;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
createHandle() {
|
|
204
|
+
var _a, _b;
|
|
205
|
+
if (typeof this.props.format === "number") {
|
|
206
|
+
throw new Error("number format");
|
|
207
|
+
}
|
|
208
|
+
const width = this.props.width || ((_a = this.props.data) == null ? void 0 : _a.width) || 1;
|
|
209
|
+
const height = this.props.height || ((_b = this.props.data) == null ? void 0 : _b.height) || 1;
|
|
210
|
+
return this.device.handle.createTexture({
|
|
211
|
+
size: {
|
|
212
|
+
width,
|
|
213
|
+
height,
|
|
214
|
+
depthOrArrayLayers: this.props.depth
|
|
215
|
+
},
|
|
216
|
+
dimension: BASE_DIMENSIONS[this.props.dimension],
|
|
217
|
+
format: getWebGPUTextureFormat(this.props.format),
|
|
218
|
+
usage: this.props.usage,
|
|
219
|
+
mipLevelCount: this.props.mipLevels,
|
|
220
|
+
sampleCount: this.props.samples
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
destroy() {
|
|
224
|
+
this.handle.destroy();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Set default sampler
|
|
228
|
+
* Accept a sampler instance or set of props;
|
|
229
|
+
*/
|
|
230
|
+
setSampler(sampler) {
|
|
231
|
+
this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
setData(options) {
|
|
235
|
+
return this.setImage({ source: options.data });
|
|
236
|
+
}
|
|
237
|
+
/** Set image */
|
|
238
|
+
setImage(options) {
|
|
239
|
+
const {
|
|
240
|
+
source,
|
|
241
|
+
width = options.source.width,
|
|
242
|
+
height = options.source.height,
|
|
243
|
+
depth = 1,
|
|
244
|
+
sourceX = 0,
|
|
245
|
+
sourceY = 0,
|
|
246
|
+
mipLevel = 0,
|
|
247
|
+
x = 0,
|
|
248
|
+
y = 0,
|
|
249
|
+
z = 0,
|
|
250
|
+
aspect = "all",
|
|
251
|
+
colorSpace = "srgb",
|
|
252
|
+
premultipliedAlpha = false
|
|
253
|
+
} = options;
|
|
254
|
+
this.device.handle.queue.copyExternalImageToTexture(
|
|
255
|
+
// source: GPUImageCopyExternalImage
|
|
256
|
+
{
|
|
257
|
+
source,
|
|
258
|
+
origin: [sourceX, sourceY]
|
|
259
|
+
},
|
|
260
|
+
// destination: GPUImageCopyTextureTagged
|
|
261
|
+
{
|
|
262
|
+
texture: this.handle,
|
|
263
|
+
origin: [x, y, z],
|
|
264
|
+
mipLevel,
|
|
265
|
+
aspect,
|
|
266
|
+
colorSpace,
|
|
267
|
+
premultipliedAlpha
|
|
268
|
+
},
|
|
269
|
+
// copySize: GPUExtent3D
|
|
270
|
+
[
|
|
271
|
+
width,
|
|
272
|
+
height,
|
|
273
|
+
depth
|
|
274
|
+
]
|
|
275
|
+
);
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
/*
|
|
279
|
+
async readPixels() {
|
|
280
|
+
const readbackBuffer = device.createBuffer({
|
|
281
|
+
usage: Buffer.COPY_DST | Buffer.MAP_READ,
|
|
282
|
+
size: 4 * textureWidth * textureHeight,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Copy data from the texture to the buffer.
|
|
286
|
+
const encoder = device.createCommandEncoder();
|
|
287
|
+
encoder.copyTextureToBuffer(
|
|
288
|
+
{ texture },
|
|
289
|
+
{ buffer, rowPitch: textureWidth * 4 },
|
|
290
|
+
[textureWidth, textureHeight],
|
|
291
|
+
);
|
|
292
|
+
device.submit([encoder.finish()]);
|
|
293
|
+
|
|
294
|
+
// Get the data on the CPU.
|
|
295
|
+
await buffer.mapAsync(GPUMapMode.READ);
|
|
296
|
+
saveScreenshot(buffer.getMappedRange());
|
|
297
|
+
buffer.unmap();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
setImageData(imageData, usage): this {
|
|
301
|
+
let data = null;
|
|
302
|
+
|
|
303
|
+
const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
|
|
304
|
+
if (bytesPerRow == img.width * 4) {
|
|
305
|
+
data = imageData.data;
|
|
306
|
+
} else {
|
|
307
|
+
data = new Uint8Array(bytesPerRow * img.height);
|
|
308
|
+
let imagePixelIndex = 0;
|
|
309
|
+
for (let y = 0; y < img.height; ++y) {
|
|
310
|
+
for (let x = 0; x < img.width; ++x) {
|
|
311
|
+
const i = x * 4 + y * bytesPerRow;
|
|
312
|
+
data[i] = imageData.data[imagePixelIndex];
|
|
313
|
+
data[i + 1] = imageData.data[imagePixelIndex + 1];
|
|
314
|
+
data[i + 2] = imageData.data[imagePixelIndex + 2];
|
|
315
|
+
data[i + 3] = imageData.data[imagePixelIndex + 3];
|
|
316
|
+
imagePixelIndex += 4;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
setData(data): this {
|
|
324
|
+
const textureDataBuffer = this.device.handle.createBuffer({
|
|
325
|
+
size: data.byteLength,
|
|
326
|
+
usage: Buffer.COPY_DST | Buffer.COPY_SRC,
|
|
327
|
+
mappedAtCreation: true
|
|
328
|
+
});
|
|
329
|
+
new Uint8Array(textureDataBuffer.getMappedRange()).set(data);
|
|
330
|
+
textureDataBuffer.unmap();
|
|
331
|
+
|
|
332
|
+
this.setBuffer(textureDataBuffer);
|
|
333
|
+
|
|
334
|
+
textureDataBuffer.destroy();
|
|
335
|
+
return this;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
setBuffer(textureDataBuffer, {bytesPerRow}): this {
|
|
339
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
340
|
+
commandEncoder.copyBufferToTexture(
|
|
341
|
+
{
|
|
342
|
+
buffer: textureDataBuffer,
|
|
343
|
+
bytesPerRow
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
texture: this.handle
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
width,
|
|
350
|
+
height,
|
|
351
|
+
depth
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
|
|
356
|
+
return this;
|
|
357
|
+
}
|
|
358
|
+
*/
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// src/adapter/resources/webgpu-external-texture.ts
|
|
362
|
+
var import_api4 = require("@luma.gl/api");
|
|
363
|
+
var WebGPUExternalTexture = class extends import_api4.ExternalTexture {
|
|
364
|
+
constructor(device, props) {
|
|
365
|
+
super(device, props);
|
|
366
|
+
this.device = device;
|
|
367
|
+
this.handle = this.props.handle || this.device.handle.importExternalTexture({
|
|
368
|
+
source: props.source,
|
|
369
|
+
colorSpace: props.colorSpace
|
|
370
|
+
});
|
|
371
|
+
this.sampler = null;
|
|
372
|
+
}
|
|
373
|
+
destroy() {
|
|
374
|
+
}
|
|
375
|
+
/** Set default sampler */
|
|
376
|
+
setSampler(sampler) {
|
|
377
|
+
this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
378
|
+
return this;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// src/adapter/resources/webgpu-shader.ts
|
|
383
|
+
var import_api5 = require("@luma.gl/api");
|
|
384
|
+
var WebGPUShader = class extends import_api5.Shader {
|
|
385
|
+
constructor(device, props) {
|
|
386
|
+
super(device, props);
|
|
387
|
+
this.device = device;
|
|
388
|
+
this.device.handle.pushErrorScope("validation");
|
|
389
|
+
this.handle = this.props.handle || this.createHandle();
|
|
390
|
+
this.handle.label = this.props.id;
|
|
391
|
+
this._checkCompilationError(this.device.handle.popErrorScope());
|
|
392
|
+
}
|
|
393
|
+
_checkCompilationError(errorScope) {
|
|
394
|
+
return __async(this, null, function* () {
|
|
395
|
+
const error = yield errorScope;
|
|
396
|
+
if (error) {
|
|
397
|
+
const shaderLog = yield this.compilationInfo();
|
|
398
|
+
import_api5.log.error(`Shader compilation error: ${error.message}`, shaderLog)();
|
|
399
|
+
throw new Error(`Shader compilation error: ${error.message}`);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
destroy() {
|
|
404
|
+
}
|
|
405
|
+
createHandle() {
|
|
406
|
+
const { source } = this.props;
|
|
407
|
+
let language = this.props.language;
|
|
408
|
+
if (!language) {
|
|
409
|
+
language = source.includes("->") ? "wgsl" : "glsl";
|
|
410
|
+
}
|
|
411
|
+
switch (language) {
|
|
412
|
+
case "wgsl":
|
|
413
|
+
return this.device.handle.createShaderModule({ code: source });
|
|
414
|
+
case "glsl":
|
|
415
|
+
return this.device.handle.createShaderModule({
|
|
416
|
+
code: source,
|
|
417
|
+
// @ts-expect-error
|
|
418
|
+
transform: (glsl) => this.device.glslang.compileGLSL(glsl, type)
|
|
419
|
+
});
|
|
420
|
+
default:
|
|
421
|
+
throw new Error(language);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/** Returns compilation info for this shader */
|
|
425
|
+
compilationInfo() {
|
|
426
|
+
return __async(this, null, function* () {
|
|
427
|
+
const compilationInfo = yield this.handle.getCompilationInfo();
|
|
428
|
+
return compilationInfo.messages;
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
434
|
+
var import_api8 = require("@luma.gl/api");
|
|
435
|
+
|
|
436
|
+
// src/adapter/helpers/webgpu-parameters.ts
|
|
437
|
+
function addDepthStencil(descriptor) {
|
|
438
|
+
descriptor.depthStencil = descriptor.depthStencil || {
|
|
439
|
+
// required, set something
|
|
440
|
+
format: "depth24plus",
|
|
441
|
+
stencilFront: {},
|
|
442
|
+
stencilBack: {},
|
|
443
|
+
// TODO can this cause trouble? Should we set to WebGPU defaults? Are there defaults?
|
|
444
|
+
depthWriteEnabled: void 0,
|
|
445
|
+
depthCompare: void 0
|
|
446
|
+
};
|
|
447
|
+
return descriptor.depthStencil;
|
|
448
|
+
}
|
|
449
|
+
var PARAMETER_TABLE = {
|
|
450
|
+
// RASTERIZATION PARAMETERS
|
|
451
|
+
cullMode: (parameter, value, descriptor) => {
|
|
452
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
453
|
+
descriptor.primitive.cullMode = value;
|
|
454
|
+
},
|
|
455
|
+
frontFace: (parameter, value, descriptor) => {
|
|
456
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
457
|
+
descriptor.primitive.frontFace = value;
|
|
458
|
+
},
|
|
459
|
+
// DEPTH
|
|
460
|
+
depthWriteEnabled: (parameter, value, descriptor) => {
|
|
461
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
462
|
+
depthStencil.depthWriteEnabled = value;
|
|
463
|
+
},
|
|
464
|
+
depthCompare: (parameter, value, descriptor) => {
|
|
465
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
466
|
+
depthStencil.depthCompare = value;
|
|
467
|
+
},
|
|
468
|
+
depthFormat: (parameter, value, descriptor) => {
|
|
469
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
470
|
+
depthStencil.format = value;
|
|
471
|
+
},
|
|
472
|
+
depthBias: (parameter, value, descriptor) => {
|
|
473
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
474
|
+
depthStencil.depthBias = value;
|
|
475
|
+
},
|
|
476
|
+
depthBiasSlopeScale: (parameter, value, descriptor) => {
|
|
477
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
478
|
+
depthStencil.depthBiasSlopeScale = value;
|
|
479
|
+
},
|
|
480
|
+
depthBiasClamp: (parameter, value, descriptor) => {
|
|
481
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
482
|
+
depthStencil.depthBiasClamp = value;
|
|
483
|
+
},
|
|
484
|
+
// STENCIL
|
|
485
|
+
stencilReadMask: (parameter, value, descriptor) => {
|
|
486
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
487
|
+
depthStencil.stencilReadMask = value;
|
|
488
|
+
},
|
|
489
|
+
stencilWriteMask: (parameter, value, descriptor) => {
|
|
490
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
491
|
+
depthStencil.stencilWriteMask = value;
|
|
492
|
+
},
|
|
493
|
+
stencilCompare: (parameter, value, descriptor) => {
|
|
494
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
495
|
+
depthStencil.stencilFront.compare = value;
|
|
496
|
+
depthStencil.stencilBack.compare = value;
|
|
497
|
+
},
|
|
498
|
+
stencilPassOperation: (parameter, value, descriptor) => {
|
|
499
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
500
|
+
depthStencil.stencilFront.passOp = value;
|
|
501
|
+
depthStencil.stencilBack.passOp = value;
|
|
502
|
+
},
|
|
503
|
+
stencilFailOperation: (parameter, value, descriptor) => {
|
|
504
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
505
|
+
depthStencil.stencilFront.failOp = value;
|
|
506
|
+
depthStencil.stencilBack.failOp = value;
|
|
507
|
+
},
|
|
508
|
+
stencilDepthFailOperation: (parameter, value, descriptor) => {
|
|
509
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
510
|
+
depthStencil.stencilFront.depthFailOp = value;
|
|
511
|
+
depthStencil.stencilBack.depthFailOp = value;
|
|
512
|
+
},
|
|
513
|
+
// MULTISAMPLE
|
|
514
|
+
sampleCount: (parameter, value, descriptor) => {
|
|
515
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
516
|
+
descriptor.multisample.count = value;
|
|
517
|
+
},
|
|
518
|
+
sampleMask: (parameter, value, descriptor) => {
|
|
519
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
520
|
+
descriptor.multisample.mask = value;
|
|
521
|
+
},
|
|
522
|
+
sampleAlphaToCoverageEnabled: (parameter, value, descriptor) => {
|
|
523
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
524
|
+
descriptor.multisample.alphaToCoverageEnabled = value;
|
|
525
|
+
},
|
|
526
|
+
// COLOR
|
|
527
|
+
colorMask: (parameter, value, descriptor) => {
|
|
528
|
+
const targets = addColorState(descriptor);
|
|
529
|
+
targets[0].writeMask = value;
|
|
530
|
+
},
|
|
531
|
+
blendColorOperation: (parameter, value, descriptor) => {
|
|
532
|
+
addColorState(descriptor);
|
|
533
|
+
}
|
|
534
|
+
/*
|
|
535
|
+
blendColorSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
536
|
+
addColorState(descriptor);
|
|
537
|
+
targets[0].blend = targets[0].blend || {};
|
|
538
|
+
targets[0].blend.color = targets[0].blend.color || {};
|
|
539
|
+
targets[0].blend.color.srcTarget = value;
|
|
540
|
+
},
|
|
541
|
+
|
|
542
|
+
blendColorDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
543
|
+
addColorState(descriptor);
|
|
544
|
+
targets[0].blend = targets[0].blend || {};
|
|
545
|
+
targets[0].blend.color = targets[0].blend.color || {};
|
|
546
|
+
targets[0].blend.color.dstTarget = value;
|
|
547
|
+
},
|
|
548
|
+
|
|
549
|
+
blendAlphaOperation: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
550
|
+
addColorState(descriptor);
|
|
551
|
+
targets[0].blend = targets[0].blend || {};
|
|
552
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
553
|
+
targets[0].blend.alpha.operation = value;
|
|
554
|
+
},
|
|
555
|
+
|
|
556
|
+
blendAlphaSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
557
|
+
addColorState(descriptor);
|
|
558
|
+
targets[0].blend = targets[0].blend || {};
|
|
559
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
560
|
+
targets[0].blend.alpha.srcTarget = value;
|
|
561
|
+
},
|
|
562
|
+
|
|
563
|
+
blendAlphaDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
564
|
+
addColorState(descriptor);
|
|
565
|
+
targets[0].blend = targets[0].blend || {};
|
|
566
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
567
|
+
targets[0].blend.alpha.dstTarget = value;
|
|
568
|
+
},
|
|
569
|
+
*/
|
|
570
|
+
};
|
|
571
|
+
var DEFAULT_PIPELINE_DESCRIPTOR = {
|
|
572
|
+
// depthStencil: {
|
|
573
|
+
// stencilFront: {},
|
|
574
|
+
// stencilBack: {},
|
|
575
|
+
// // depthWriteEnabled: true,
|
|
576
|
+
// // depthCompare: 'less',
|
|
577
|
+
// // format: 'depth24plus-stencil8',
|
|
578
|
+
// },
|
|
579
|
+
primitive: {
|
|
580
|
+
cullMode: "back",
|
|
581
|
+
topology: "triangle-list"
|
|
582
|
+
},
|
|
583
|
+
vertex: {
|
|
584
|
+
module: void 0,
|
|
585
|
+
entryPoint: "main"
|
|
586
|
+
},
|
|
587
|
+
fragment: {
|
|
588
|
+
module: void 0,
|
|
589
|
+
entryPoint: "main",
|
|
590
|
+
targets: [
|
|
591
|
+
// { format: props.color0Format || 'bgra8unorm' }
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
layout: "auto"
|
|
595
|
+
};
|
|
596
|
+
function applyParametersToRenderPipelineDescriptor(pipelineDescriptor, parameters = {}) {
|
|
597
|
+
Object.assign(pipelineDescriptor, __spreadValues(__spreadValues({}, DEFAULT_PIPELINE_DESCRIPTOR), pipelineDescriptor));
|
|
598
|
+
setParameters(pipelineDescriptor, parameters);
|
|
599
|
+
}
|
|
600
|
+
function setParameters(pipelineDescriptor, parameters) {
|
|
601
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
602
|
+
const setterFunction = PARAMETER_TABLE[key];
|
|
603
|
+
if (!setterFunction) {
|
|
604
|
+
throw new Error(`Illegal parameter ${key}`);
|
|
605
|
+
}
|
|
606
|
+
setterFunction(key, value, pipelineDescriptor);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
function addColorState(descriptor) {
|
|
610
|
+
var _a, _b, _c, _d, _e, _f;
|
|
611
|
+
descriptor.fragment.targets = ((_a = descriptor.fragment) == null ? void 0 : _a.targets) || [];
|
|
612
|
+
if (!Array.isArray((_b = descriptor.fragment) == null ? void 0 : _b.targets)) {
|
|
613
|
+
throw new Error("colorstate");
|
|
614
|
+
}
|
|
615
|
+
if (((_d = (_c = descriptor.fragment) == null ? void 0 : _c.targets) == null ? void 0 : _d.length) === 0) {
|
|
616
|
+
(_e = descriptor.fragment.targets) == null ? void 0 : _e.push({});
|
|
617
|
+
}
|
|
618
|
+
return (_f = descriptor.fragment) == null ? void 0 : _f.targets;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// src/adapter/helpers/get-bind-group.ts
|
|
622
|
+
var import_api6 = require("@luma.gl/api");
|
|
623
|
+
function getBindGroup(device, bindGroupLayout, layout, bindings) {
|
|
624
|
+
const entries = getBindGroupEntries(bindings, layout);
|
|
625
|
+
return device.createBindGroup({
|
|
626
|
+
layout: bindGroupLayout,
|
|
627
|
+
entries
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
function getShaderLayoutBinding(layout, bindingName) {
|
|
631
|
+
const bindingLayout = layout.bindings.find((binding) => binding.name === bindingName);
|
|
632
|
+
if (!bindingLayout) {
|
|
633
|
+
import_api6.log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
634
|
+
}
|
|
635
|
+
return bindingLayout;
|
|
636
|
+
}
|
|
637
|
+
function getBindGroupEntries(bindings, layout) {
|
|
638
|
+
const entries = [];
|
|
639
|
+
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
640
|
+
const bindingLayout = getShaderLayoutBinding(layout, bindingName);
|
|
641
|
+
if (bindingLayout) {
|
|
642
|
+
entries.push(getBindGroupEntry(value, bindingLayout.location));
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return entries;
|
|
646
|
+
}
|
|
647
|
+
function getBindGroupEntry(binding, index) {
|
|
648
|
+
if (binding instanceof import_api6.Buffer) {
|
|
649
|
+
return {
|
|
650
|
+
binding: index,
|
|
651
|
+
resource: {
|
|
652
|
+
buffer: (0, import_api6.cast)(binding).handle
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
if (binding instanceof import_api6.Sampler) {
|
|
657
|
+
return {
|
|
658
|
+
binding: index,
|
|
659
|
+
resource: (0, import_api6.cast)(binding).handle
|
|
660
|
+
};
|
|
661
|
+
} else if (binding instanceof import_api6.Texture) {
|
|
662
|
+
return {
|
|
663
|
+
binding: index,
|
|
664
|
+
resource: (0, import_api6.cast)(binding).handle.createView()
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
throw new Error("invalid binding");
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/adapter/helpers/get-vertex-buffer-layout.ts
|
|
671
|
+
var import_api7 = require("@luma.gl/api");
|
|
672
|
+
function getVertexBufferLayout(layout, bufferMap) {
|
|
673
|
+
const vertexBufferLayouts = [];
|
|
674
|
+
const usedAttributes = /* @__PURE__ */ new Set();
|
|
675
|
+
for (const mapping of bufferMap) {
|
|
676
|
+
const vertexAttributes = [];
|
|
677
|
+
let stepMode = "vertex";
|
|
678
|
+
let byteStride = 0;
|
|
679
|
+
const byteOffset = mapping.byteOffset || 0;
|
|
680
|
+
if ("attributes" in mapping) {
|
|
681
|
+
for (const interleaved of mapping.attributes) {
|
|
682
|
+
const attributeLayout = findAttributeLayout(layout, interleaved.name, usedAttributes);
|
|
683
|
+
stepMode = attributeLayout.stepMode || "vertex";
|
|
684
|
+
vertexAttributes.push({
|
|
685
|
+
format: attributeLayout.format,
|
|
686
|
+
offset: byteOffset + byteStride,
|
|
687
|
+
shaderLocation: attributeLayout.location
|
|
688
|
+
});
|
|
689
|
+
byteStride += (0, import_api7.decodeVertexFormat)(attributeLayout.format).byteLength;
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
const attributeLayout = findAttributeLayout(layout, mapping.name, usedAttributes);
|
|
693
|
+
byteStride = (0, import_api7.decodeVertexFormat)(attributeLayout.format).byteLength;
|
|
694
|
+
stepMode = attributeLayout.stepMode || "vertex";
|
|
695
|
+
vertexAttributes.push({
|
|
696
|
+
format: attributeLayout.format,
|
|
697
|
+
offset: byteOffset,
|
|
698
|
+
shaderLocation: attributeLayout.location
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
vertexBufferLayouts.push({
|
|
702
|
+
arrayStride: mapping.byteStride || byteStride,
|
|
703
|
+
stepMode: stepMode || "vertex",
|
|
704
|
+
attributes: vertexAttributes
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
for (const attribute of layout.attributes) {
|
|
708
|
+
if (!usedAttributes.has(attribute.name)) {
|
|
709
|
+
vertexBufferLayouts.push({
|
|
710
|
+
arrayStride: (0, import_api7.decodeVertexFormat)(attribute.format).byteLength,
|
|
711
|
+
stepMode: attribute.stepMode || "vertex",
|
|
712
|
+
attributes: [{
|
|
713
|
+
format: attribute.format,
|
|
714
|
+
offset: 0,
|
|
715
|
+
shaderLocation: attribute.location
|
|
716
|
+
}]
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return vertexBufferLayouts;
|
|
721
|
+
}
|
|
722
|
+
function getBufferSlots(layout, bufferMap) {
|
|
723
|
+
const usedAttributes = /* @__PURE__ */ new Set();
|
|
724
|
+
let bufferSlot = 0;
|
|
725
|
+
const bufferSlots = {};
|
|
726
|
+
for (const mapping of bufferMap) {
|
|
727
|
+
if ("attributes" in mapping) {
|
|
728
|
+
for (const interleaved of mapping.attributes) {
|
|
729
|
+
usedAttributes.add(interleaved.name);
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
usedAttributes.add(mapping.name);
|
|
733
|
+
}
|
|
734
|
+
bufferSlots[mapping.name] = bufferSlot++;
|
|
735
|
+
}
|
|
736
|
+
for (const attribute of layout.attributes) {
|
|
737
|
+
if (!usedAttributes.has(attribute.name)) {
|
|
738
|
+
bufferSlots[attribute.name] = bufferSlot++;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return bufferSlots;
|
|
742
|
+
}
|
|
743
|
+
function findAttributeLayout(layout, name, attributeNames) {
|
|
744
|
+
const attribute = layout.attributes.find((attribute2) => attribute2.name === name);
|
|
745
|
+
if (!attribute) {
|
|
746
|
+
throw new Error(`Unknown attribute ${name}`);
|
|
747
|
+
}
|
|
748
|
+
if (attributeNames.has(name)) {
|
|
749
|
+
throw new Error(`Duplicate attribute ${name}`);
|
|
750
|
+
}
|
|
751
|
+
attributeNames.add(name);
|
|
752
|
+
return attribute;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
756
|
+
var WebGPURenderPipeline = class extends import_api8.RenderPipeline {
|
|
757
|
+
constructor(device, props) {
|
|
758
|
+
super(device, props);
|
|
759
|
+
this.fs = null;
|
|
760
|
+
this._indexBuffer = null;
|
|
761
|
+
this._bindGroup = null;
|
|
762
|
+
this.device = device;
|
|
763
|
+
this.handle = this.props.handle || this.createHandle();
|
|
764
|
+
this.handle.label = this.props.id;
|
|
765
|
+
this.vs = (0, import_api8.cast)(props.vs);
|
|
766
|
+
this.fs = (0, import_api8.cast)(props.fs);
|
|
767
|
+
this._bufferSlots = getBufferSlots(this.props.layout, this.props.bufferMap);
|
|
768
|
+
this._buffers = new Array(Object.keys(this._bufferSlots).length).fill(null);
|
|
769
|
+
this._bindGroupLayout = this.handle.getBindGroupLayout(0);
|
|
770
|
+
}
|
|
771
|
+
createHandle() {
|
|
772
|
+
const descriptor = this._getRenderPipelineDescriptor();
|
|
773
|
+
const renderPipeline = this.device.handle.createRenderPipeline(descriptor);
|
|
774
|
+
import_api8.log.groupCollapsed(1, `new WebGPRenderPipeline(${this.id})`)();
|
|
775
|
+
import_api8.log.log(1, JSON.stringify(descriptor, null, 2))();
|
|
776
|
+
import_api8.log.groupEnd(1)();
|
|
777
|
+
return renderPipeline;
|
|
778
|
+
}
|
|
779
|
+
destroy() {
|
|
780
|
+
}
|
|
781
|
+
setIndexBuffer(indexBuffer) {
|
|
782
|
+
this._indexBuffer = (0, import_api8.cast)(indexBuffer);
|
|
783
|
+
}
|
|
784
|
+
setAttributes(attributes) {
|
|
785
|
+
for (const [name, buffer] of Object.entries(attributes)) {
|
|
786
|
+
const bufferIndex = this._bufferSlots[name];
|
|
787
|
+
if (bufferIndex >= 0) {
|
|
788
|
+
this._buffers[bufferIndex] = buffer;
|
|
789
|
+
} else {
|
|
790
|
+
throw new Error(
|
|
791
|
+
`Setting attribute '${name}' not listed in shader layout for program ${this.id}`
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
/** Set the bindings */
|
|
797
|
+
setBindings(bindings) {
|
|
798
|
+
if (!(0, import_api8.isObjectEmpty)(this.props.bindings)) {
|
|
799
|
+
Object.assign(this.props.bindings, bindings);
|
|
800
|
+
this._bindGroup = getBindGroup(
|
|
801
|
+
this.device.handle,
|
|
802
|
+
this._bindGroupLayout,
|
|
803
|
+
this.props.layout,
|
|
804
|
+
this.props.bindings
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
setUniforms(uniforms) {
|
|
809
|
+
if (!(0, import_api8.isObjectEmpty)(uniforms)) {
|
|
810
|
+
throw new Error("WebGPU does not support uniforms");
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
_getBuffers() {
|
|
814
|
+
return this._buffers;
|
|
815
|
+
}
|
|
816
|
+
/** Return a bind group created by setBindings */
|
|
817
|
+
_getBindGroup() {
|
|
818
|
+
return this._bindGroup;
|
|
819
|
+
}
|
|
820
|
+
/** Populate the complex WebGPU GPURenderPipelineDescriptor */
|
|
821
|
+
_getRenderPipelineDescriptor() {
|
|
822
|
+
var _a, _b;
|
|
823
|
+
const vertex = {
|
|
824
|
+
module: (0, import_api8.cast)(this.props.vs).handle,
|
|
825
|
+
entryPoint: this.props.vsEntryPoint || "main",
|
|
826
|
+
buffers: getVertexBufferLayout(this.props.layout, this.props.bufferMap)
|
|
827
|
+
};
|
|
828
|
+
let fragment;
|
|
829
|
+
if (this.props.fs) {
|
|
830
|
+
fragment = {
|
|
831
|
+
module: (0, import_api8.cast)(this.props.fs).handle,
|
|
832
|
+
entryPoint: this.props.fsEntryPoint || "main",
|
|
833
|
+
targets: [
|
|
834
|
+
{
|
|
835
|
+
// TODO exclamation mark hack!
|
|
836
|
+
format: getWebGPUTextureFormat((_b = (_a = this.device) == null ? void 0 : _a.canvasContext) == null ? void 0 : _b.format)
|
|
837
|
+
}
|
|
838
|
+
]
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
switch (this.props.topology) {
|
|
842
|
+
case "triangle-fan":
|
|
843
|
+
case "line-loop":
|
|
844
|
+
throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);
|
|
845
|
+
default:
|
|
846
|
+
}
|
|
847
|
+
const descriptor = {
|
|
848
|
+
vertex,
|
|
849
|
+
fragment,
|
|
850
|
+
primitive: {
|
|
851
|
+
topology: this.props.topology
|
|
852
|
+
},
|
|
853
|
+
layout: "auto"
|
|
854
|
+
};
|
|
855
|
+
applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
|
|
856
|
+
return descriptor;
|
|
857
|
+
}
|
|
858
|
+
draw(options) {
|
|
859
|
+
const webgpuRenderPass = (0, import_api8.cast)(options.renderPass) || this.device.getDefaultRenderPass();
|
|
860
|
+
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
861
|
+
const bindGroup = this._getBindGroup();
|
|
862
|
+
if (bindGroup) {
|
|
863
|
+
webgpuRenderPass.handle.setBindGroup(0, bindGroup);
|
|
864
|
+
}
|
|
865
|
+
this._setAttributeBuffers(webgpuRenderPass);
|
|
866
|
+
if (options.indexCount) {
|
|
867
|
+
webgpuRenderPass.handle.drawIndexed(
|
|
868
|
+
options.indexCount,
|
|
869
|
+
options.instanceCount,
|
|
870
|
+
options.firstIndex,
|
|
871
|
+
options.baseVertex,
|
|
872
|
+
options.firstInstance
|
|
873
|
+
);
|
|
874
|
+
} else {
|
|
875
|
+
webgpuRenderPass.handle.draw(
|
|
876
|
+
options.vertexCount || 0,
|
|
877
|
+
options.instanceCount,
|
|
878
|
+
options.firstIndex,
|
|
879
|
+
options.firstInstance
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
_setAttributeBuffers(webgpuRenderPass) {
|
|
884
|
+
if (this._indexBuffer) {
|
|
885
|
+
webgpuRenderPass.handle.setIndexBuffer(this._indexBuffer.handle, this._indexBuffer.props.indexType);
|
|
886
|
+
}
|
|
887
|
+
const buffers = this._getBuffers();
|
|
888
|
+
for (let i = 0; i < buffers.length; ++i) {
|
|
889
|
+
const buffer = (0, import_api8.cast)(buffers[i]);
|
|
890
|
+
if (!buffer) {
|
|
891
|
+
const attribute = this.props.layout.attributes.find(
|
|
892
|
+
(attribute2) => attribute2.location === i
|
|
893
|
+
);
|
|
894
|
+
throw new Error(
|
|
895
|
+
`No buffer provided for attribute '${(attribute == null ? void 0 : attribute.name) || ""}' in Model '${this.props.id}'`
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
webgpuRenderPass.handle.setVertexBuffer(i, buffer.handle);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
// src/adapter/resources/webgpu-compute-pipeline.ts
|
|
904
|
+
var import_api9 = require("@luma.gl/api");
|
|
905
|
+
var WebGPUComputePipeline = class extends import_api9.ComputePipeline {
|
|
906
|
+
constructor(device, props) {
|
|
907
|
+
super(device, props);
|
|
908
|
+
this.device = device;
|
|
909
|
+
const module2 = (0, import_api9.cast)(this.props.cs).handle;
|
|
910
|
+
this.handle = this.props.handle || this.device.handle.createComputePipeline({
|
|
911
|
+
label: this.props.id,
|
|
912
|
+
compute: {
|
|
913
|
+
module: module2,
|
|
914
|
+
entryPoint: this.props.csEntryPoint
|
|
915
|
+
// constants: this.props.csConstants
|
|
916
|
+
},
|
|
917
|
+
layout: "auto"
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
/** For internal use in render passes */
|
|
921
|
+
_getBindGroupLayout() {
|
|
922
|
+
return this.handle.getBindGroupLayout(0);
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
// src/adapter/resources/webgpu-render-pass.ts
|
|
927
|
+
var import_api10 = require("@luma.gl/api");
|
|
928
|
+
var WebGPURenderPass = class extends import_api10.RenderPass {
|
|
929
|
+
constructor(device, props = {}) {
|
|
930
|
+
super(device, props);
|
|
931
|
+
/** Active pipeline */
|
|
932
|
+
this.pipeline = null;
|
|
933
|
+
this.device = device;
|
|
934
|
+
const framebuffer = props.framebuffer || device.canvasContext.getCurrentFramebuffer();
|
|
935
|
+
const renderPassDescriptor = framebuffer.renderPassDescriptor;
|
|
936
|
+
this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
937
|
+
this.handle.label = this.props.id;
|
|
938
|
+
}
|
|
939
|
+
destroy() {
|
|
940
|
+
}
|
|
941
|
+
end() {
|
|
942
|
+
this.handle.end();
|
|
943
|
+
}
|
|
944
|
+
setPipeline(pipeline) {
|
|
945
|
+
this.pipeline = (0, import_api10.cast)(pipeline);
|
|
946
|
+
this.handle.setPipeline(this.pipeline.handle);
|
|
947
|
+
}
|
|
948
|
+
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
949
|
+
setBindings(bindings) {
|
|
950
|
+
var _a, _b;
|
|
951
|
+
(_a = this.pipeline) == null ? void 0 : _a.setBindings(bindings);
|
|
952
|
+
const bindGroup = (_b = this.pipeline) == null ? void 0 : _b._getBindGroup();
|
|
953
|
+
if (bindGroup) {
|
|
954
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
setIndexBuffer(buffer, indexFormat, offset = 0, size) {
|
|
958
|
+
this.handle.setIndexBuffer((0, import_api10.cast)(buffer).handle, indexFormat, offset, size);
|
|
959
|
+
}
|
|
960
|
+
setVertexBuffer(slot, buffer, offset = 0) {
|
|
961
|
+
this.handle.setVertexBuffer(slot, (0, import_api10.cast)(buffer).handle, offset);
|
|
962
|
+
}
|
|
963
|
+
draw(options) {
|
|
964
|
+
if (options.indexCount) {
|
|
965
|
+
this.handle.drawIndexed(
|
|
966
|
+
options.indexCount,
|
|
967
|
+
options.instanceCount,
|
|
968
|
+
options.firstIndex,
|
|
969
|
+
options.baseVertex,
|
|
970
|
+
options.firstInstance
|
|
971
|
+
);
|
|
972
|
+
} else {
|
|
973
|
+
this.handle.draw(
|
|
974
|
+
options.vertexCount || 0,
|
|
975
|
+
options.instanceCount,
|
|
976
|
+
options.firstIndex,
|
|
977
|
+
options.firstInstance
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
drawIndirect() {
|
|
982
|
+
}
|
|
983
|
+
setParameters(parameters) {
|
|
984
|
+
const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
|
|
985
|
+
if (blendConstant) {
|
|
986
|
+
this.handle.setBlendConstant(blendConstant);
|
|
987
|
+
}
|
|
988
|
+
if (stencilReference) {
|
|
989
|
+
this.handle.setStencilReference(stencilReference);
|
|
990
|
+
}
|
|
991
|
+
if (scissorRect) {
|
|
992
|
+
this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
|
|
993
|
+
}
|
|
994
|
+
if (viewport) {
|
|
995
|
+
this.handle.setViewport(
|
|
996
|
+
viewport[0],
|
|
997
|
+
viewport[1],
|
|
998
|
+
viewport[2],
|
|
999
|
+
viewport[3],
|
|
1000
|
+
viewport[4],
|
|
1001
|
+
viewport[5]
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
pushDebugGroup(groupLabel) {
|
|
1006
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1007
|
+
}
|
|
1008
|
+
popDebugGroup() {
|
|
1009
|
+
this.handle.popDebugGroup();
|
|
1010
|
+
}
|
|
1011
|
+
insertDebugMarker(markerLabel) {
|
|
1012
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1013
|
+
}
|
|
1014
|
+
// writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1015
|
+
// beginOcclusionQuery(queryIndex: number): void;
|
|
1016
|
+
// endOcclusionQuery(): void;
|
|
1017
|
+
// beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1018
|
+
// endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1019
|
+
// executeBundles(bundles: Iterable<GPURenderBundle>): void;
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1022
|
+
// src/adapter/resources/webgpu-compute-pass.ts
|
|
1023
|
+
var import_api11 = require("@luma.gl/api");
|
|
1024
|
+
var WebGPUComputePass = class extends import_api11.ComputePass {
|
|
1025
|
+
constructor(device, props) {
|
|
1026
|
+
var _a;
|
|
1027
|
+
super(device, props);
|
|
1028
|
+
this._bindGroupLayout = null;
|
|
1029
|
+
this.device = device;
|
|
1030
|
+
this.handle = this.props.handle || ((_a = device.commandEncoder) == null ? void 0 : _a.beginComputePass({
|
|
1031
|
+
label: this.props.id
|
|
1032
|
+
// timestampWrites?: GPUComputePassTimestampWrites;
|
|
1033
|
+
}));
|
|
1034
|
+
}
|
|
1035
|
+
/** @note no WebGPU destroy method, just gc */
|
|
1036
|
+
destroy() {
|
|
1037
|
+
}
|
|
1038
|
+
end() {
|
|
1039
|
+
this.handle.end();
|
|
1040
|
+
}
|
|
1041
|
+
setPipeline(pipeline) {
|
|
1042
|
+
const wgpuPipeline = (0, import_api11.cast)(pipeline);
|
|
1043
|
+
this.handle.setPipeline(wgpuPipeline.handle);
|
|
1044
|
+
this._bindGroupLayout = wgpuPipeline._getBindGroupLayout();
|
|
1045
|
+
}
|
|
1046
|
+
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
1047
|
+
setBindings(bindings) {
|
|
1048
|
+
throw new Error("fix me");
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1052
|
+
* @param x X dimension of the grid of workgroups to dispatch.
|
|
1053
|
+
* @param y Y dimension of the grid of workgroups to dispatch.
|
|
1054
|
+
* @param z Z dimension of the grid of workgroups to dispatch.
|
|
1055
|
+
*/
|
|
1056
|
+
dispatch(x, y, z) {
|
|
1057
|
+
this.handle.dispatchWorkgroups(x, y, z);
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1061
|
+
* @param indirectBuffer buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
|
|
1062
|
+
* @param indirectOffset
|
|
1063
|
+
*/
|
|
1064
|
+
dispatchIndirect(indirectBuffer, indirectOffset = 0) {
|
|
1065
|
+
this.handle.dispatchWorkgroupsIndirect((0, import_api11.cast)(indirectBuffer).handle, indirectOffset);
|
|
1066
|
+
}
|
|
1067
|
+
pushDebugGroup(groupLabel) {
|
|
1068
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1069
|
+
}
|
|
1070
|
+
popDebugGroup() {
|
|
1071
|
+
this.handle.popDebugGroup();
|
|
1072
|
+
}
|
|
1073
|
+
insertDebugMarker(markerLabel) {
|
|
1074
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1075
|
+
}
|
|
1076
|
+
// writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1077
|
+
// beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1078
|
+
// endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
// src/adapter/webgpu-canvas-context.ts
|
|
1082
|
+
var import_api13 = require("@luma.gl/api");
|
|
1083
|
+
|
|
1084
|
+
// src/adapter/resources/webgpu-framebuffer.ts
|
|
1085
|
+
var import_api12 = require("@luma.gl/api");
|
|
1086
|
+
var WebGPUFramebuffer = class extends import_api12.Framebuffer {
|
|
1087
|
+
constructor(device, props) {
|
|
1088
|
+
super(device, props);
|
|
1089
|
+
this.colorAttachments = [];
|
|
1090
|
+
this.depthStencilAttachment = null;
|
|
1091
|
+
/** Partial render pass descriptor. Used by WebGPURenderPass */
|
|
1092
|
+
this.renderPassDescriptor = {
|
|
1093
|
+
colorAttachments: []
|
|
1094
|
+
};
|
|
1095
|
+
this.device = device;
|
|
1096
|
+
if (props.depthStencilAttachment) {
|
|
1097
|
+
this.depthStencilAttachment = this.createDepthStencilTexture(props);
|
|
1098
|
+
}
|
|
1099
|
+
if (props.colorAttachments) {
|
|
1100
|
+
this.colorAttachments = props.colorAttachments.map((colorAttachment) => this.createColorTexture(this.props, colorAttachment));
|
|
1101
|
+
}
|
|
1102
|
+
if (this.depthStencilAttachment) {
|
|
1103
|
+
this.renderPassDescriptor.depthStencilAttachment = {
|
|
1104
|
+
view: this.depthStencilAttachment.handle.createView(),
|
|
1105
|
+
// Add default clear values
|
|
1106
|
+
depthClearValue: 1,
|
|
1107
|
+
depthStoreOp: "store",
|
|
1108
|
+
stencilClearValue: 0,
|
|
1109
|
+
stencilStoreOp: "store"
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
if (this.colorAttachments.length > 0) {
|
|
1113
|
+
this.renderPassDescriptor.colorAttachments = this.colorAttachments.map((colorAttachment) => ({
|
|
1114
|
+
view: colorAttachment.handle.createView(),
|
|
1115
|
+
loadOp: "clear",
|
|
1116
|
+
loadValue: [0, 0, 0, 0],
|
|
1117
|
+
storeOp: "store"
|
|
1118
|
+
}));
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
/** Create depth stencil texture */
|
|
1122
|
+
createDepthStencilTexture(props) {
|
|
1123
|
+
if (props.depthStencilAttachment instanceof WebGPUTexture) {
|
|
1124
|
+
return props.depthStencilAttachment;
|
|
1125
|
+
}
|
|
1126
|
+
if (typeof props.depthStencilAttachment === "string") {
|
|
1127
|
+
return this.device._createTexture({
|
|
1128
|
+
id: "depth-stencil-attachment",
|
|
1129
|
+
format: props.depthStencilAttachment,
|
|
1130
|
+
width: props.width,
|
|
1131
|
+
height: props.height,
|
|
1132
|
+
usage: import_api12.Texture.RENDER_ATTACHMENT
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
throw new Error("type");
|
|
1136
|
+
}
|
|
1137
|
+
createColorTexture(props, texture) {
|
|
1138
|
+
if (texture instanceof WebGPUTexture) {
|
|
1139
|
+
return texture;
|
|
1140
|
+
}
|
|
1141
|
+
if (typeof texture === "string") {
|
|
1142
|
+
return this.device._createTexture({
|
|
1143
|
+
id: "color-attachment",
|
|
1144
|
+
format: texture,
|
|
1145
|
+
width: props.width,
|
|
1146
|
+
height: props.height,
|
|
1147
|
+
usage: import_api12.Texture.RENDER_ATTACHMENT
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
throw new Error("type");
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Create new textures with correct size for all attachments.
|
|
1154
|
+
* @note destroys existing textures.
|
|
1155
|
+
*/
|
|
1156
|
+
_resizeAttachments(width, height) {
|
|
1157
|
+
for (let i = 0; i < this.colorAttachments.length; ++i) {
|
|
1158
|
+
if (this.colorAttachments[i]) {
|
|
1159
|
+
const resizedTexture = this.device._createTexture(__spreadProps(__spreadValues({}, this.colorAttachments[i].props), { width, height }));
|
|
1160
|
+
this.colorAttachments[i].destroy();
|
|
1161
|
+
this.colorAttachments[i] = resizedTexture;
|
|
1162
|
+
this.renderPassDescriptor.colorAttachments[i].view = resizedTexture.handle.createView();
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (this.depthStencilAttachment) {
|
|
1166
|
+
const resizedTexture = this.device._createTexture(__spreadProps(__spreadValues({}, this.depthStencilAttachment.props), { width, height }));
|
|
1167
|
+
this.depthStencilAttachment.destroy();
|
|
1168
|
+
this.depthStencilAttachment = resizedTexture;
|
|
1169
|
+
this.renderPassDescriptor.depthStencilAttachment.view = resizedTexture.handle.createView();
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
// src/adapter/webgpu-canvas-context.ts
|
|
1175
|
+
var WebGPUCanvasContext = class extends import_api13.CanvasContext {
|
|
1176
|
+
constructor(device, adapter, props) {
|
|
1177
|
+
super(props);
|
|
1178
|
+
this.depthStencilFormat = "depth24plus";
|
|
1179
|
+
this.sampleCount = 1;
|
|
1180
|
+
this.depthStencilAttachment = null;
|
|
1181
|
+
this.device = device;
|
|
1182
|
+
this.width = -1;
|
|
1183
|
+
this.height = -1;
|
|
1184
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
1185
|
+
this.gpuCanvasContext = this.canvas.getContext("webgpu");
|
|
1186
|
+
this.format = this.gpuCanvasContext.getPreferredFormat(adapter);
|
|
1187
|
+
}
|
|
1188
|
+
destroy() {
|
|
1189
|
+
this.gpuCanvasContext.unconfigure();
|
|
1190
|
+
}
|
|
1191
|
+
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
1192
|
+
getCurrentFramebuffer() {
|
|
1193
|
+
this.update();
|
|
1194
|
+
const currentColorAttachment = this.device.createTexture({
|
|
1195
|
+
id: "default-render-target",
|
|
1196
|
+
handle: this.gpuCanvasContext.getCurrentTexture(),
|
|
1197
|
+
format: this.format,
|
|
1198
|
+
width: this.width,
|
|
1199
|
+
height: this.height
|
|
1200
|
+
});
|
|
1201
|
+
this._createDepthStencilAttachment();
|
|
1202
|
+
return new WebGPUFramebuffer(this.device, {
|
|
1203
|
+
colorAttachments: [currentColorAttachment],
|
|
1204
|
+
depthStencilAttachment: this.depthStencilAttachment
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
/** Resizes and updates render targets if necessary */
|
|
1208
|
+
update() {
|
|
1209
|
+
const [width, height] = this.getPixelSize();
|
|
1210
|
+
const sizeChanged = width !== this.width || height !== this.height;
|
|
1211
|
+
if (sizeChanged) {
|
|
1212
|
+
this.width = width;
|
|
1213
|
+
this.height = height;
|
|
1214
|
+
if (this.depthStencilAttachment) {
|
|
1215
|
+
this.depthStencilAttachment.destroy();
|
|
1216
|
+
this.depthStencilAttachment = null;
|
|
1217
|
+
}
|
|
1218
|
+
this.gpuCanvasContext.configure({
|
|
1219
|
+
device: this.device.handle,
|
|
1220
|
+
format: getWebGPUTextureFormat(this.format),
|
|
1221
|
+
// size: [this.width, this.height],
|
|
1222
|
+
colorSpace: this.props.colorSpace,
|
|
1223
|
+
alphaMode: this.props.alphaMode
|
|
1224
|
+
});
|
|
1225
|
+
import_api13.log.log(1, `Resized to ${this.width}x${this.height}px`)();
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
resize(options) {
|
|
1229
|
+
this.update();
|
|
1230
|
+
}
|
|
1231
|
+
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
1232
|
+
_createDepthStencilAttachment() {
|
|
1233
|
+
if (!this.depthStencilAttachment) {
|
|
1234
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
1235
|
+
id: "depth-stencil-target",
|
|
1236
|
+
format: this.depthStencilFormat,
|
|
1237
|
+
width: this.width,
|
|
1238
|
+
height: this.height,
|
|
1239
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
return this.depthStencilAttachment;
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
// src/adapter/webgpu-device.ts
|
|
1247
|
+
var _WebGPUDevice = class extends import_api14.Device {
|
|
1248
|
+
constructor(device, adapter, props) {
|
|
1249
|
+
super(__spreadProps(__spreadValues({}, props), { id: props.id || (0, import_api14.uid)("webgpu-device") }));
|
|
1250
|
+
this.canvasContext = null;
|
|
1251
|
+
this.commandEncoder = null;
|
|
1252
|
+
this.renderPass = null;
|
|
1253
|
+
this._isLost = false;
|
|
1254
|
+
this.handle = device;
|
|
1255
|
+
this.adapter = adapter;
|
|
1256
|
+
this._info = {
|
|
1257
|
+
type: "webgpu",
|
|
1258
|
+
vendor: this.adapter.__brand,
|
|
1259
|
+
renderer: "",
|
|
1260
|
+
version: "",
|
|
1261
|
+
gpu: "unknown",
|
|
1262
|
+
// 'nvidia' | 'amd' | 'intel' | 'apple' | 'unknown',
|
|
1263
|
+
shadingLanguages: ["glsl", "wgsl"],
|
|
1264
|
+
shadingLanguageVersions: {
|
|
1265
|
+
glsl: "450",
|
|
1266
|
+
wgsl: "100"
|
|
1267
|
+
},
|
|
1268
|
+
vendorMasked: "",
|
|
1269
|
+
rendererMasked: ""
|
|
1270
|
+
};
|
|
1271
|
+
this.lost = new Promise((resolve) => __async(this, null, function* () {
|
|
1272
|
+
const lostInfo = yield this.handle.lost;
|
|
1273
|
+
this._isLost = true;
|
|
1274
|
+
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
1275
|
+
}));
|
|
1276
|
+
if (props.canvas) {
|
|
1277
|
+
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, { canvas: props.canvas });
|
|
1278
|
+
}
|
|
1279
|
+
this.features = this._getFeatures();
|
|
1280
|
+
}
|
|
1281
|
+
/** Check if WebGPU is available */
|
|
1282
|
+
static isSupported() {
|
|
1283
|
+
return Boolean(typeof navigator !== "undefined" && navigator.gpu);
|
|
1284
|
+
}
|
|
1285
|
+
static create(props) {
|
|
1286
|
+
return __async(this, null, function* () {
|
|
1287
|
+
if (!navigator.gpu) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
"WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu"
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
import_api14.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
1293
|
+
const adapter = yield navigator.gpu.requestAdapter({
|
|
1294
|
+
powerPreference: "high-performance"
|
|
1295
|
+
// forceSoftware: false
|
|
1296
|
+
});
|
|
1297
|
+
if (!adapter) {
|
|
1298
|
+
throw new Error("Failed to request WebGPU adapter");
|
|
1299
|
+
}
|
|
1300
|
+
import_api14.log.probe(1, "Adapter available")();
|
|
1301
|
+
const gpuDevice = yield adapter.requestDevice({
|
|
1302
|
+
requiredFeatures: adapter.features
|
|
1303
|
+
// TODO ensure we obtain best limits
|
|
1304
|
+
// requiredLimits: adapter.limits
|
|
1305
|
+
});
|
|
1306
|
+
import_api14.log.probe(1, "GPUDevice available")();
|
|
1307
|
+
if (typeof props.canvas === "string") {
|
|
1308
|
+
yield import_api14.CanvasContext.pageLoaded;
|
|
1309
|
+
import_api14.log.probe(1, "DOM is loaded")();
|
|
1310
|
+
}
|
|
1311
|
+
const device = new _WebGPUDevice(gpuDevice, adapter, props);
|
|
1312
|
+
import_api14.log.probe(1, "Device created", device.info)();
|
|
1313
|
+
import_api14.log.table(1, device.info)();
|
|
1314
|
+
import_api14.log.groupEnd(1)();
|
|
1315
|
+
return device;
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
// TODO
|
|
1319
|
+
// Load the glslang module now so that it is available synchronously when compiling shaders
|
|
1320
|
+
// const {glsl = true} = props;
|
|
1321
|
+
// this.glslang = glsl && await loadGlslangModule();
|
|
1322
|
+
destroy() {
|
|
1323
|
+
this.handle.destroy();
|
|
1324
|
+
}
|
|
1325
|
+
get info() {
|
|
1326
|
+
return this._info;
|
|
1327
|
+
}
|
|
1328
|
+
get limits() {
|
|
1329
|
+
return this.handle.limits;
|
|
1330
|
+
}
|
|
1331
|
+
isTextureFormatSupported(format) {
|
|
1332
|
+
return !format.includes("webgl");
|
|
1333
|
+
}
|
|
1334
|
+
/** @todo implement proper check? */
|
|
1335
|
+
isTextureFormatFilterable(format) {
|
|
1336
|
+
return this.isTextureFormatSupported(format);
|
|
1337
|
+
}
|
|
1338
|
+
/** @todo implement proper check? */
|
|
1339
|
+
isTextureFormatRenderable(format) {
|
|
1340
|
+
return this.isTextureFormatSupported(format);
|
|
1341
|
+
}
|
|
1342
|
+
get isLost() {
|
|
1343
|
+
return this._isLost;
|
|
1344
|
+
}
|
|
1345
|
+
_createBuffer(props) {
|
|
1346
|
+
return new WebGPUBuffer(this, props);
|
|
1347
|
+
}
|
|
1348
|
+
_createTexture(props) {
|
|
1349
|
+
return new WebGPUTexture(this, props);
|
|
1350
|
+
}
|
|
1351
|
+
createExternalTexture(props) {
|
|
1352
|
+
return new WebGPUExternalTexture(this, props);
|
|
1353
|
+
}
|
|
1354
|
+
createShader(props) {
|
|
1355
|
+
return new WebGPUShader(this, props);
|
|
1356
|
+
}
|
|
1357
|
+
createSampler(props) {
|
|
1358
|
+
return new WebGPUSampler(this, props);
|
|
1359
|
+
}
|
|
1360
|
+
createRenderPipeline(props) {
|
|
1361
|
+
return new WebGPURenderPipeline(this, props);
|
|
1362
|
+
}
|
|
1363
|
+
createFramebuffer(props) {
|
|
1364
|
+
throw new Error("Not implemented");
|
|
1365
|
+
}
|
|
1366
|
+
createComputePipeline(props) {
|
|
1367
|
+
return new WebGPUComputePipeline(this, props);
|
|
1368
|
+
}
|
|
1369
|
+
// WebGPU specifics
|
|
1370
|
+
/**
|
|
1371
|
+
* Allows a render pass to begin against a canvas context
|
|
1372
|
+
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1373
|
+
*/
|
|
1374
|
+
beginRenderPass(props) {
|
|
1375
|
+
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1376
|
+
return new WebGPURenderPass(this, props);
|
|
1377
|
+
}
|
|
1378
|
+
beginComputePass(props) {
|
|
1379
|
+
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1380
|
+
return new WebGPUComputePass(this, props);
|
|
1381
|
+
}
|
|
1382
|
+
createCanvasContext(props) {
|
|
1383
|
+
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Gets default renderpass encoder.
|
|
1387
|
+
* Creates a new encoder against default canvasContext if not already created
|
|
1388
|
+
* @note Called internally by Model.
|
|
1389
|
+
*/
|
|
1390
|
+
getDefaultRenderPass() {
|
|
1391
|
+
var _a;
|
|
1392
|
+
this.renderPass = this.renderPass || this.beginRenderPass({
|
|
1393
|
+
framebuffer: (_a = this.canvasContext) == null ? void 0 : _a.getCurrentFramebuffer()
|
|
1394
|
+
});
|
|
1395
|
+
return this.renderPass;
|
|
1396
|
+
}
|
|
1397
|
+
submit() {
|
|
1398
|
+
var _a, _b;
|
|
1399
|
+
(_a = this.renderPass) == null ? void 0 : _a.end();
|
|
1400
|
+
const commandBuffer = (_b = this.commandEncoder) == null ? void 0 : _b.finish();
|
|
1401
|
+
if (commandBuffer) {
|
|
1402
|
+
this.handle.queue.submit([commandBuffer]);
|
|
1403
|
+
}
|
|
1404
|
+
this.commandEncoder = null;
|
|
1405
|
+
this.renderPass = null;
|
|
1406
|
+
}
|
|
1407
|
+
_getFeatures() {
|
|
1408
|
+
const features = new Set(this.handle.features);
|
|
1409
|
+
if (features.has("depth-clamping")) {
|
|
1410
|
+
features.delete("depth-clamping");
|
|
1411
|
+
features.add("depth-clip-control");
|
|
1412
|
+
}
|
|
1413
|
+
if (features.has("texture-compression-bc")) {
|
|
1414
|
+
features.add("texture-compression-bc5-webgl");
|
|
1415
|
+
}
|
|
1416
|
+
features.add("webgpu");
|
|
1417
|
+
features.add("timer-query-webgl");
|
|
1418
|
+
features.add("vertex-array-object-webgl1");
|
|
1419
|
+
features.add("instanced-rendering-webgl1");
|
|
1420
|
+
features.add("multiple-render-targets-webgl1");
|
|
1421
|
+
features.add("index-uint32-webgl1");
|
|
1422
|
+
features.add("blend-minmax-webgl1");
|
|
1423
|
+
features.add("texture-blend-float-webgl1");
|
|
1424
|
+
features.add("texture-formats-srgb-webgl1");
|
|
1425
|
+
features.add("texture-formats-depth-webgl1");
|
|
1426
|
+
features.add("texture-formats-float32-webgl1");
|
|
1427
|
+
features.add("texture-formats-float16-webgl1");
|
|
1428
|
+
features.add("texture-filter-linear-float32-webgl");
|
|
1429
|
+
features.add("texture-filter-linear-float16-webgl");
|
|
1430
|
+
features.add("texture-filter-anisotropic-webgl");
|
|
1431
|
+
features.add("texture-renderable-rgba32float-webgl");
|
|
1432
|
+
features.add("texture-renderable-float32-webgl");
|
|
1433
|
+
features.add("texture-renderable-float16-webgl");
|
|
1434
|
+
features.add("glsl-frag-data");
|
|
1435
|
+
features.add("glsl-frag-depth");
|
|
1436
|
+
features.add("glsl-derivatives");
|
|
1437
|
+
features.add("glsl-texture-lod");
|
|
1438
|
+
return features;
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
var WebGPUDevice = _WebGPUDevice;
|
|
1442
|
+
WebGPUDevice.type = "webgpu";
|