@luma.gl/webgpu 9.0.0-alpha.9 → 9.0.0-beta.10
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 +3 -1
- package/dist/adapter/helpers/accessor-to-format.js +102 -1
- package/dist/adapter/helpers/convert-texture-format.d.ts +2 -2
- package/dist/adapter/helpers/convert-texture-format.d.ts.map +1 -1
- package/dist/adapter/helpers/convert-texture-format.js +8 -6
- package/dist/adapter/helpers/get-bind-group.d.ts +4 -4
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +61 -52
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +5 -5
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +123 -90
- package/dist/adapter/helpers/webgpu-parameters.d.ts +2 -2
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +184 -130
- package/dist/adapter/resources/webgpu-buffer.d.ts +14 -5
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +117 -70
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +13 -14
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +83 -65
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +19 -13
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +78 -57
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +16 -6
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +48 -26
- package/dist/adapter/resources/webgpu-external-texture.d.ts +5 -5
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js +38 -29
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +4 -21
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +15 -109
- package/dist/adapter/resources/webgpu-query-set.d.ts +17 -0
- package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-query-set.js +27 -0
- package/dist/adapter/resources/webgpu-render-pass.d.ts +14 -7
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +136 -91
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +63 -23
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +151 -148
- package/dist/adapter/resources/webgpu-sampler.d.ts +5 -5
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +23 -23
- package/dist/adapter/resources/webgpu-shader.d.ts +9 -12
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +47 -60
- package/dist/adapter/resources/webgpu-texture-view.d.ts +20 -0
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-texture-view.js +35 -0
- package/dist/adapter/resources/webgpu-texture.d.ts +20 -10
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +133 -105
- package/dist/adapter/resources/webgpu-vertex-array.d.ts +27 -0
- package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-vertex-array.js +66 -0
- package/dist/adapter/webgpu-canvas-context.d.ts +17 -12
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +105 -92
- package/dist/adapter/webgpu-device.d.ts +45 -30
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +266 -241
- package/dist/dist.dev.js +1664 -0
- package/dist/dist.min.js +9 -0
- package/dist/index.cjs +1432 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -8
- package/dist.min.js +9 -0
- package/package.json +22 -11
- package/src/adapter/helpers/accessor-to-format.ts +6 -3
- package/src/adapter/helpers/convert-texture-format.ts +5 -2
- package/src/adapter/helpers/get-bind-group.ts +30 -14
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +73 -39
- package/src/adapter/helpers/webgpu-parameters.ts +99 -29
- package/src/adapter/resources/webgpu-buffer.ts +85 -17
- package/src/adapter/resources/webgpu-command-encoder.ts +93 -58
- package/src/adapter/resources/webgpu-compute-pass.ts +56 -32
- package/src/adapter/resources/webgpu-compute-pipeline.ts +51 -18
- package/src/adapter/resources/webgpu-external-texture.ts +19 -11
- package/src/adapter/resources/webgpu-framebuffer.ts +11 -108
- package/src/adapter/resources/webgpu-query-set.ts +37 -0
- package/src/adapter/resources/webgpu-render-pass.ts +95 -19
- package/src/adapter/resources/webgpu-render-pipeline.ts +139 -159
- package/src/adapter/resources/webgpu-sampler.ts +10 -7
- package/src/adapter/resources/webgpu-shader.ts +30 -35
- package/src/adapter/resources/webgpu-texture-view.ts +46 -0
- package/src/adapter/resources/webgpu-texture.ts +75 -41
- package/src/adapter/resources/webgpu-vertex-array.ts +91 -0
- package/src/adapter/webgpu-canvas-context.ts +60 -29
- package/src/adapter/webgpu-device.ts +219 -120
- package/src/index.ts +8 -9
- package/dist/adapter/helpers/accessor-to-format.js.map +0 -1
- package/dist/adapter/helpers/convert-texture-format.js.map +0 -1
- package/dist/adapter/helpers/generate-mipmaps.d.ts +0 -10
- package/dist/adapter/helpers/generate-mipmaps.d.ts.map +0 -1
- package/dist/adapter/helpers/generate-mipmaps.js +0 -95
- package/dist/adapter/helpers/generate-mipmaps.js.map +0 -1
- package/dist/adapter/helpers/get-bind-group.js.map +0 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +0 -1
- package/dist/adapter/helpers/webgpu-parameters.js.map +0 -1
- package/dist/adapter/resources/webgpu-buffer.js.map +0 -1
- package/dist/adapter/resources/webgpu-command-encoder.js.map +0 -1
- package/dist/adapter/resources/webgpu-compute-pass.js.map +0 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +0 -1
- package/dist/adapter/resources/webgpu-external-texture.js.map +0 -1
- package/dist/adapter/resources/webgpu-framebuffer.js.map +0 -1
- package/dist/adapter/resources/webgpu-query.d.ts +0 -1
- package/dist/adapter/resources/webgpu-query.d.ts.map +0 -1
- package/dist/adapter/resources/webgpu-query.js +0 -2
- package/dist/adapter/resources/webgpu-query.js.map +0 -1
- package/dist/adapter/resources/webgpu-render-pass.js.map +0 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +0 -1
- package/dist/adapter/resources/webgpu-sampler.js.map +0 -1
- package/dist/adapter/resources/webgpu-shader.js.map +0 -1
- package/dist/adapter/resources/webgpu-texture.js.map +0 -1
- package/dist/adapter/webgpu-canvas-context.js.map +0 -1
- package/dist/adapter/webgpu-device.js.map +0 -1
- package/dist/adapter/webgpu-types.d.ts +0 -1
- package/dist/adapter/webgpu-types.d.ts.map +0 -1
- package/dist/adapter/webgpu-types.js +0 -2
- package/dist/adapter/webgpu-types.js.map +0 -1
- 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/glsl/glsllang.d.ts +0 -3
- package/dist/glsl/glsllang.d.ts.map +0 -1
- package/dist/glsl/glsllang.js +0 -10
- package/dist/glsl/glsllang.js.map +0 -1
- package/dist/index.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/adapter/helpers/generate-mipmaps.ts +0 -107
- package/src/adapter/resources/webgpu-query.ts +0 -43
- package/src/adapter/webgpu-types.ts +0 -0
- package/src/bundle.ts +0 -4
- package/src/glsl/glsllang.ts +0 -14
- package/src/init.ts +0 -4
package/dist/dist.dev.js
ADDED
|
@@ -0,0 +1,1664 @@
|
|
|
1
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
2
|
+
if (typeof exports === 'object' && typeof module === 'object')
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
else if (typeof define === 'function' && define.amd) define([], factory);
|
|
5
|
+
else if (typeof exports === 'object') exports['luma'] = factory();
|
|
6
|
+
else root['luma'] = factory();})(globalThis, function () {
|
|
7
|
+
var __exports__ = (() => {
|
|
8
|
+
var __create = Object.create;
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
15
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
16
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
17
|
+
};
|
|
18
|
+
var __export = (target, all) => {
|
|
19
|
+
for (var name in all)
|
|
20
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
21
|
+
};
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(from))
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
26
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
27
|
+
}
|
|
28
|
+
return to;
|
|
29
|
+
};
|
|
30
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
31
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
32
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
33
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
34
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
35
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
36
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
37
|
+
mod
|
|
38
|
+
));
|
|
39
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
40
|
+
var __publicField = (obj, key, value) => {
|
|
41
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
42
|
+
return value;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// external-global-plugin:@luma.gl/core
|
|
46
|
+
var require_core = __commonJS({
|
|
47
|
+
"external-global-plugin:@luma.gl/core"(exports, module) {
|
|
48
|
+
module.exports = globalThis.luma;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// bundle.ts
|
|
53
|
+
var bundle_exports = {};
|
|
54
|
+
__export(bundle_exports, {
|
|
55
|
+
WebGPUBuffer: () => WebGPUBuffer,
|
|
56
|
+
WebGPUDevice: () => WebGPUDevice,
|
|
57
|
+
WebGPUSampler: () => WebGPUSampler,
|
|
58
|
+
WebGPUShader: () => WebGPUShader,
|
|
59
|
+
WebGPUTexture: () => WebGPUTexture
|
|
60
|
+
});
|
|
61
|
+
__reExport(bundle_exports, __toESM(require_core(), 1));
|
|
62
|
+
|
|
63
|
+
// src/adapter/webgpu-device.ts
|
|
64
|
+
var import_core17 = __toESM(require_core(), 1);
|
|
65
|
+
|
|
66
|
+
// src/adapter/resources/webgpu-buffer.ts
|
|
67
|
+
var import_core = __toESM(require_core(), 1);
|
|
68
|
+
function getByteLength(props) {
|
|
69
|
+
return props.byteLength || props.data?.byteLength || 0;
|
|
70
|
+
}
|
|
71
|
+
var WebGPUBuffer = class extends import_core.Buffer {
|
|
72
|
+
device;
|
|
73
|
+
handle;
|
|
74
|
+
byteLength;
|
|
75
|
+
constructor(device, props) {
|
|
76
|
+
super(device, props);
|
|
77
|
+
this.device = device;
|
|
78
|
+
this.byteLength = getByteLength(props);
|
|
79
|
+
const mapBuffer = Boolean(props.data);
|
|
80
|
+
const size = Math.ceil(this.byteLength / 4) * 4;
|
|
81
|
+
this.handle = this.props.handle || this.device.handle.createBuffer({
|
|
82
|
+
size,
|
|
83
|
+
// usage defaults to vertex
|
|
84
|
+
usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
85
|
+
mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
|
|
86
|
+
label: this.props.id
|
|
87
|
+
});
|
|
88
|
+
if (props.data) {
|
|
89
|
+
this._writeMapped(props.data);
|
|
90
|
+
}
|
|
91
|
+
if (mapBuffer && !props.mappedAtCreation) {
|
|
92
|
+
this.handle.unmap();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
destroy() {
|
|
96
|
+
this.handle?.destroy();
|
|
97
|
+
this.handle = null;
|
|
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
|
+
async readAsync(byteOffset = 0, byteLength = this.byteLength) {
|
|
110
|
+
const tempBuffer = new WebGPUBuffer(this.device, {
|
|
111
|
+
usage: import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST,
|
|
112
|
+
byteLength
|
|
113
|
+
});
|
|
114
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
115
|
+
commandEncoder.copyBufferToBuffer(this.handle, byteOffset, tempBuffer.handle, 0, byteLength);
|
|
116
|
+
this.device.handle.queue.submit([commandEncoder.finish()]);
|
|
117
|
+
await tempBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
|
|
118
|
+
const arrayBuffer = tempBuffer.handle.getMappedRange().slice(0);
|
|
119
|
+
tempBuffer.handle.unmap();
|
|
120
|
+
tempBuffer.destroy();
|
|
121
|
+
return new Uint8Array(arrayBuffer);
|
|
122
|
+
}
|
|
123
|
+
_writeMapped(typedArray) {
|
|
124
|
+
const arrayBuffer = this.handle.getMappedRange();
|
|
125
|
+
new typedArray.constructor(arrayBuffer).set(typedArray);
|
|
126
|
+
}
|
|
127
|
+
// WEBGPU API
|
|
128
|
+
mapAsync(mode, offset = 0, size) {
|
|
129
|
+
return this.handle.mapAsync(mode, offset, size);
|
|
130
|
+
}
|
|
131
|
+
getMappedRange(offset = 0, size) {
|
|
132
|
+
return this.handle.getMappedRange(offset, size);
|
|
133
|
+
}
|
|
134
|
+
unmap() {
|
|
135
|
+
this.handle.unmap();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/adapter/resources/webgpu-texture.ts
|
|
140
|
+
var import_core4 = __toESM(require_core(), 1);
|
|
141
|
+
|
|
142
|
+
// src/adapter/helpers/convert-texture-format.ts
|
|
143
|
+
function getWebGPUTextureFormat(format) {
|
|
144
|
+
if (format.includes("webgl")) {
|
|
145
|
+
throw new Error("webgl-only format");
|
|
146
|
+
}
|
|
147
|
+
return format;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/adapter/resources/webgpu-sampler.ts
|
|
151
|
+
var import_core2 = __toESM(require_core(), 1);
|
|
152
|
+
var WebGPUSampler = class extends import_core2.Sampler {
|
|
153
|
+
device;
|
|
154
|
+
handle;
|
|
155
|
+
constructor(device, props) {
|
|
156
|
+
super(device, props);
|
|
157
|
+
this.device = device;
|
|
158
|
+
const samplerProps = { ...this.props };
|
|
159
|
+
if (samplerProps.type !== "comparison-sampler") {
|
|
160
|
+
delete samplerProps.compare;
|
|
161
|
+
}
|
|
162
|
+
this.handle = this.handle || this.device.handle.createSampler(samplerProps);
|
|
163
|
+
this.handle.label = this.props.id;
|
|
164
|
+
}
|
|
165
|
+
destroy() {
|
|
166
|
+
this.handle = null;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/adapter/resources/webgpu-texture-view.ts
|
|
171
|
+
var import_core3 = __toESM(require_core(), 1);
|
|
172
|
+
var WebGPUTextureView = class extends import_core3.TextureView {
|
|
173
|
+
device;
|
|
174
|
+
handle;
|
|
175
|
+
texture;
|
|
176
|
+
constructor(device, props) {
|
|
177
|
+
super(device, props);
|
|
178
|
+
this.device = device;
|
|
179
|
+
this.texture = props.texture;
|
|
180
|
+
this.handle = this.handle || this.texture.handle.createView({
|
|
181
|
+
format: props.format || this.texture.format,
|
|
182
|
+
dimension: props.dimension || this.texture.dimension,
|
|
183
|
+
aspect: props.aspect,
|
|
184
|
+
baseMipLevel: props.baseMipLevel,
|
|
185
|
+
mipLevelCount: props.mipLevelCount,
|
|
186
|
+
// GPUIntegerCoordinate;
|
|
187
|
+
baseArrayLayer: props.baseArrayLayer,
|
|
188
|
+
// GPUIntegerCoordinate;
|
|
189
|
+
arrayLayerCount: props.arrayLayerCount
|
|
190
|
+
// GPUIntegerCoordinate;
|
|
191
|
+
});
|
|
192
|
+
this.handle.label = this.props.id;
|
|
193
|
+
}
|
|
194
|
+
destroy() {
|
|
195
|
+
this.handle = null;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/adapter/resources/webgpu-texture.ts
|
|
200
|
+
var BASE_DIMENSIONS = {
|
|
201
|
+
"1d": "1d",
|
|
202
|
+
"2d": "2d",
|
|
203
|
+
"2d-array": "2d",
|
|
204
|
+
cube: "2d",
|
|
205
|
+
"cube-array": "2d",
|
|
206
|
+
"3d": "3d"
|
|
207
|
+
};
|
|
208
|
+
var WebGPUTexture = class extends import_core4.Texture {
|
|
209
|
+
device;
|
|
210
|
+
handle;
|
|
211
|
+
height = 1;
|
|
212
|
+
width = 1;
|
|
213
|
+
sampler;
|
|
214
|
+
view;
|
|
215
|
+
// static async createFromImageURL(src, usage = 0) {
|
|
216
|
+
// const img = document.createElement('img');
|
|
217
|
+
// img.src = src;
|
|
218
|
+
// await img.decode();
|
|
219
|
+
// return WebGPUTexture(img, usage);
|
|
220
|
+
// }
|
|
221
|
+
constructor(device, props) {
|
|
222
|
+
super(device, props);
|
|
223
|
+
this.device = device;
|
|
224
|
+
if (props.data instanceof Promise) {
|
|
225
|
+
props.data.then((resolvedImageData) => {
|
|
226
|
+
this.props = { ...props, data: resolvedImageData };
|
|
227
|
+
this.initialize(this.props);
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.initialize(props);
|
|
232
|
+
}
|
|
233
|
+
destroy() {
|
|
234
|
+
this.handle?.destroy();
|
|
235
|
+
this.handle = null;
|
|
236
|
+
}
|
|
237
|
+
createView(props) {
|
|
238
|
+
return new WebGPUTextureView(this.device, { ...props, texture: this });
|
|
239
|
+
}
|
|
240
|
+
initialize(props) {
|
|
241
|
+
this.handle = this.props.handle || this.createHandle();
|
|
242
|
+
this.handle.label ||= this.id;
|
|
243
|
+
if (this.props.data) {
|
|
244
|
+
this.setData({ data: this.props.data });
|
|
245
|
+
}
|
|
246
|
+
this.width = this.handle.width;
|
|
247
|
+
this.height = this.handle.height;
|
|
248
|
+
this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler);
|
|
249
|
+
this.view = new WebGPUTextureView(this.device, { ...this.props, texture: this });
|
|
250
|
+
}
|
|
251
|
+
createHandle() {
|
|
252
|
+
const width = this.props.width || this.props.data?.width || 1;
|
|
253
|
+
const height = this.props.height || this.props.data?.height || 1;
|
|
254
|
+
return this.device.handle.createTexture({
|
|
255
|
+
label: this.id,
|
|
256
|
+
size: {
|
|
257
|
+
width,
|
|
258
|
+
height,
|
|
259
|
+
depthOrArrayLayers: this.props.depth
|
|
260
|
+
},
|
|
261
|
+
dimension: BASE_DIMENSIONS[this.props.dimension],
|
|
262
|
+
format: getWebGPUTextureFormat(this.props.format),
|
|
263
|
+
usage: this.props.usage,
|
|
264
|
+
mipLevelCount: this.props.mipLevels,
|
|
265
|
+
sampleCount: this.props.samples
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Set default sampler
|
|
270
|
+
* Accept a sampler instance or set of props;
|
|
271
|
+
*/
|
|
272
|
+
setSampler(sampler) {
|
|
273
|
+
this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
274
|
+
return this;
|
|
275
|
+
}
|
|
276
|
+
setData(options) {
|
|
277
|
+
return this.setImage({ source: options.data });
|
|
278
|
+
}
|
|
279
|
+
/** Set image */
|
|
280
|
+
setImage(options) {
|
|
281
|
+
const {
|
|
282
|
+
source,
|
|
283
|
+
width = options.source.width,
|
|
284
|
+
height = options.source.height,
|
|
285
|
+
depth = 1,
|
|
286
|
+
sourceX = 0,
|
|
287
|
+
sourceY = 0,
|
|
288
|
+
mipLevel = 0,
|
|
289
|
+
x = 0,
|
|
290
|
+
y = 0,
|
|
291
|
+
z = 0,
|
|
292
|
+
aspect = "all",
|
|
293
|
+
colorSpace = "srgb",
|
|
294
|
+
premultipliedAlpha = false
|
|
295
|
+
} = options;
|
|
296
|
+
this.device.handle.queue.copyExternalImageToTexture(
|
|
297
|
+
// source: GPUImageCopyExternalImage
|
|
298
|
+
{
|
|
299
|
+
source,
|
|
300
|
+
origin: [sourceX, sourceY]
|
|
301
|
+
},
|
|
302
|
+
// destination: GPUImageCopyTextureTagged
|
|
303
|
+
{
|
|
304
|
+
texture: this.handle,
|
|
305
|
+
origin: [x, y, z],
|
|
306
|
+
mipLevel,
|
|
307
|
+
aspect,
|
|
308
|
+
colorSpace,
|
|
309
|
+
premultipliedAlpha
|
|
310
|
+
},
|
|
311
|
+
// copySize: GPUExtent3D
|
|
312
|
+
[width, height, depth]
|
|
313
|
+
);
|
|
314
|
+
return { width, height };
|
|
315
|
+
}
|
|
316
|
+
// WebGPU specific
|
|
317
|
+
/*
|
|
318
|
+
async readPixels() {
|
|
319
|
+
const readbackBuffer = device.createBuffer({
|
|
320
|
+
usage: Buffer.COPY_DST | Buffer.MAP_READ,
|
|
321
|
+
size: 4 * textureWidth * textureHeight,
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Copy data from the texture to the buffer.
|
|
325
|
+
const encoder = device.createCommandEncoder();
|
|
326
|
+
encoder.copyTextureToBuffer(
|
|
327
|
+
{ texture },
|
|
328
|
+
{ buffer, rowPitch: textureWidth * 4 },
|
|
329
|
+
[textureWidth, textureHeight],
|
|
330
|
+
);
|
|
331
|
+
device.submit([encoder.finish()]);
|
|
332
|
+
|
|
333
|
+
// Get the data on the CPU.
|
|
334
|
+
await buffer.mapAsync(GPUMapMode.READ);
|
|
335
|
+
saveScreenshot(buffer.getMappedRange());
|
|
336
|
+
buffer.unmap();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
setImageData(imageData, usage): this {
|
|
340
|
+
let data = null;
|
|
341
|
+
|
|
342
|
+
const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
|
|
343
|
+
if (bytesPerRow == img.width * 4) {
|
|
344
|
+
data = imageData.data;
|
|
345
|
+
} else {
|
|
346
|
+
data = new Uint8Array(bytesPerRow * img.height);
|
|
347
|
+
let imagePixelIndex = 0;
|
|
348
|
+
for (let y = 0; y < img.height; ++y) {
|
|
349
|
+
for (let x = 0; x < img.width; ++x) {
|
|
350
|
+
const i = x * 4 + y * bytesPerRow;
|
|
351
|
+
data[i] = imageData.data[imagePixelIndex];
|
|
352
|
+
data[i + 1] = imageData.data[imagePixelIndex + 1];
|
|
353
|
+
data[i + 2] = imageData.data[imagePixelIndex + 2];
|
|
354
|
+
data[i + 3] = imageData.data[imagePixelIndex + 3];
|
|
355
|
+
imagePixelIndex += 4;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return this;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
setData(data): this {
|
|
363
|
+
const textureDataBuffer = this.device.handle.createBuffer({
|
|
364
|
+
size: data.byteLength,
|
|
365
|
+
usage: Buffer.COPY_DST | Buffer.COPY_SRC,
|
|
366
|
+
mappedAtCreation: true
|
|
367
|
+
});
|
|
368
|
+
new Uint8Array(textureDataBuffer.getMappedRange()).set(data);
|
|
369
|
+
textureDataBuffer.unmap();
|
|
370
|
+
|
|
371
|
+
this.setBuffer(textureDataBuffer);
|
|
372
|
+
|
|
373
|
+
textureDataBuffer.destroy();
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
setBuffer(textureDataBuffer, {bytesPerRow}): this {
|
|
378
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
379
|
+
commandEncoder.copyBufferToTexture(
|
|
380
|
+
{
|
|
381
|
+
buffer: textureDataBuffer,
|
|
382
|
+
bytesPerRow
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
texture: this.handle
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
width,
|
|
389
|
+
height,
|
|
390
|
+
depth
|
|
391
|
+
}
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
|
|
395
|
+
return this;
|
|
396
|
+
}
|
|
397
|
+
*/
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// src/adapter/resources/webgpu-external-texture.ts
|
|
401
|
+
var import_core5 = __toESM(require_core(), 1);
|
|
402
|
+
var WebGPUExternalTexture = class extends import_core5.ExternalTexture {
|
|
403
|
+
device;
|
|
404
|
+
handle;
|
|
405
|
+
sampler;
|
|
406
|
+
constructor(device, props) {
|
|
407
|
+
super(device, props);
|
|
408
|
+
this.device = device;
|
|
409
|
+
this.handle = this.props.handle || this.device.handle.importExternalTexture({
|
|
410
|
+
source: props.source,
|
|
411
|
+
colorSpace: props.colorSpace
|
|
412
|
+
});
|
|
413
|
+
this.sampler = null;
|
|
414
|
+
}
|
|
415
|
+
destroy() {
|
|
416
|
+
this.handle = null;
|
|
417
|
+
}
|
|
418
|
+
/** Set default sampler */
|
|
419
|
+
setSampler(sampler) {
|
|
420
|
+
this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/adapter/resources/webgpu-shader.ts
|
|
426
|
+
var import_core6 = __toESM(require_core(), 1);
|
|
427
|
+
var WebGPUShader = class extends import_core6.Shader {
|
|
428
|
+
device;
|
|
429
|
+
handle;
|
|
430
|
+
constructor(device, props) {
|
|
431
|
+
super(device, props);
|
|
432
|
+
this.device = device;
|
|
433
|
+
this.device.handle.pushErrorScope("validation");
|
|
434
|
+
this.handle = this.props.handle || this.createHandle();
|
|
435
|
+
this.handle.label = this.props.id;
|
|
436
|
+
this._checkCompilationError(this.device.handle.popErrorScope());
|
|
437
|
+
}
|
|
438
|
+
async _checkCompilationError(errorScope) {
|
|
439
|
+
const error = await errorScope;
|
|
440
|
+
if (error) {
|
|
441
|
+
this.debugShader();
|
|
442
|
+
const shaderLog = await this.getCompilationInfo();
|
|
443
|
+
import_core6.log.error(`Shader compilation error: ${error.message}`, shaderLog)();
|
|
444
|
+
throw new Error(`Shader compilation error: ${error.message}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
destroy() {
|
|
448
|
+
this.handle = null;
|
|
449
|
+
}
|
|
450
|
+
/** Returns compilation info for this shader */
|
|
451
|
+
async getCompilationInfo() {
|
|
452
|
+
const compilationInfo = await this.handle.getCompilationInfo();
|
|
453
|
+
return compilationInfo.messages;
|
|
454
|
+
}
|
|
455
|
+
// PRIVATE METHODS
|
|
456
|
+
createHandle() {
|
|
457
|
+
const { source } = this.props;
|
|
458
|
+
const isGLSL = source.includes("#version");
|
|
459
|
+
if (this.props.language === "glsl" || isGLSL) {
|
|
460
|
+
throw new Error("GLSL shaders are not supported in WebGPU");
|
|
461
|
+
}
|
|
462
|
+
return this.device.handle.createShaderModule({ code: source });
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
467
|
+
var import_core9 = __toESM(require_core(), 1);
|
|
468
|
+
|
|
469
|
+
// src/adapter/helpers/webgpu-parameters.ts
|
|
470
|
+
function addDepthStencil(descriptor) {
|
|
471
|
+
descriptor.depthStencil = descriptor.depthStencil || {
|
|
472
|
+
// required, set something
|
|
473
|
+
format: "depth24plus",
|
|
474
|
+
stencilFront: {},
|
|
475
|
+
stencilBack: {},
|
|
476
|
+
// TODO can this cause trouble? Should we set to WebGPU defaults? Are there defaults?
|
|
477
|
+
depthWriteEnabled: false,
|
|
478
|
+
depthCompare: "less-equal"
|
|
479
|
+
};
|
|
480
|
+
return descriptor.depthStencil;
|
|
481
|
+
}
|
|
482
|
+
var PARAMETER_TABLE = {
|
|
483
|
+
// RASTERIZATION PARAMETERS
|
|
484
|
+
cullMode: (parameter, value, descriptor) => {
|
|
485
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
486
|
+
descriptor.primitive.cullMode = value;
|
|
487
|
+
},
|
|
488
|
+
frontFace: (parameter, value, descriptor) => {
|
|
489
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
490
|
+
descriptor.primitive.frontFace = value;
|
|
491
|
+
},
|
|
492
|
+
// DEPTH
|
|
493
|
+
depthWriteEnabled: (parameter, value, descriptor) => {
|
|
494
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
495
|
+
depthStencil.depthWriteEnabled = value;
|
|
496
|
+
},
|
|
497
|
+
depthCompare: (parameter, value, descriptor) => {
|
|
498
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
499
|
+
depthStencil.depthCompare = value;
|
|
500
|
+
},
|
|
501
|
+
depthFormat: (parameter, value, descriptor) => {
|
|
502
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
503
|
+
depthStencil.format = value;
|
|
504
|
+
},
|
|
505
|
+
depthBias: (parameter, value, descriptor) => {
|
|
506
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
507
|
+
depthStencil.depthBias = value;
|
|
508
|
+
},
|
|
509
|
+
depthBiasSlopeScale: (parameter, value, descriptor) => {
|
|
510
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
511
|
+
depthStencil.depthBiasSlopeScale = value;
|
|
512
|
+
},
|
|
513
|
+
depthBiasClamp: (parameter, value, descriptor) => {
|
|
514
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
515
|
+
depthStencil.depthBiasClamp = value;
|
|
516
|
+
},
|
|
517
|
+
// STENCIL
|
|
518
|
+
stencilReadMask: (parameter, value, descriptor) => {
|
|
519
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
520
|
+
depthStencil.stencilReadMask = value;
|
|
521
|
+
},
|
|
522
|
+
stencilWriteMask: (parameter, value, descriptor) => {
|
|
523
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
524
|
+
depthStencil.stencilWriteMask = value;
|
|
525
|
+
},
|
|
526
|
+
stencilCompare: (parameter, value, descriptor) => {
|
|
527
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
528
|
+
depthStencil.stencilFront.compare = value;
|
|
529
|
+
depthStencil.stencilBack.compare = value;
|
|
530
|
+
},
|
|
531
|
+
stencilPassOperation: (parameter, value, descriptor) => {
|
|
532
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
533
|
+
depthStencil.stencilFront.passOp = value;
|
|
534
|
+
depthStencil.stencilBack.passOp = value;
|
|
535
|
+
},
|
|
536
|
+
stencilFailOperation: (parameter, value, descriptor) => {
|
|
537
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
538
|
+
depthStencil.stencilFront.failOp = value;
|
|
539
|
+
depthStencil.stencilBack.failOp = value;
|
|
540
|
+
},
|
|
541
|
+
stencilDepthFailOperation: (parameter, value, descriptor) => {
|
|
542
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
543
|
+
depthStencil.stencilFront.depthFailOp = value;
|
|
544
|
+
depthStencil.stencilBack.depthFailOp = value;
|
|
545
|
+
},
|
|
546
|
+
// MULTISAMPLE
|
|
547
|
+
sampleCount: (parameter, value, descriptor) => {
|
|
548
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
549
|
+
descriptor.multisample.count = value;
|
|
550
|
+
},
|
|
551
|
+
sampleMask: (parameter, value, descriptor) => {
|
|
552
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
553
|
+
descriptor.multisample.mask = value;
|
|
554
|
+
},
|
|
555
|
+
sampleAlphaToCoverageEnabled: (parameter, value, descriptor) => {
|
|
556
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
557
|
+
descriptor.multisample.alphaToCoverageEnabled = value;
|
|
558
|
+
},
|
|
559
|
+
// COLOR
|
|
560
|
+
colorMask: (parameter, value, descriptor) => {
|
|
561
|
+
const targets = addColorState(descriptor);
|
|
562
|
+
targets[0].writeMask = value;
|
|
563
|
+
},
|
|
564
|
+
blendColorOperation: (parameter, value, descriptor) => {
|
|
565
|
+
addColorState(descriptor);
|
|
566
|
+
}
|
|
567
|
+
/*
|
|
568
|
+
blendColorSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
569
|
+
addColorState(descriptor);
|
|
570
|
+
targets[0].blend = targets[0].blend || {};
|
|
571
|
+
targets[0].blend.color = targets[0].blend.color || {};
|
|
572
|
+
targets[0].blend.color.srcTarget = value;
|
|
573
|
+
},
|
|
574
|
+
|
|
575
|
+
blendColorDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
576
|
+
addColorState(descriptor);
|
|
577
|
+
targets[0].blend = targets[0].blend || {};
|
|
578
|
+
targets[0].blend.color = targets[0].blend.color || {};
|
|
579
|
+
targets[0].blend.color.dstTarget = value;
|
|
580
|
+
},
|
|
581
|
+
|
|
582
|
+
blendAlphaOperation: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
583
|
+
addColorState(descriptor);
|
|
584
|
+
targets[0].blend = targets[0].blend || {};
|
|
585
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
586
|
+
targets[0].blend.alpha.operation = value;
|
|
587
|
+
},
|
|
588
|
+
|
|
589
|
+
blendAlphaSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
590
|
+
addColorState(descriptor);
|
|
591
|
+
targets[0].blend = targets[0].blend || {};
|
|
592
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
593
|
+
targets[0].blend.alpha.srcTarget = value;
|
|
594
|
+
},
|
|
595
|
+
|
|
596
|
+
blendAlphaDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
597
|
+
addColorState(descriptor);
|
|
598
|
+
targets[0].blend = targets[0].blend || {};
|
|
599
|
+
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
600
|
+
targets[0].blend.alpha.dstTarget = value;
|
|
601
|
+
},
|
|
602
|
+
*/
|
|
603
|
+
};
|
|
604
|
+
var DEFAULT_PIPELINE_DESCRIPTOR = {
|
|
605
|
+
// depthStencil: {
|
|
606
|
+
// stencilFront: {},
|
|
607
|
+
// stencilBack: {},
|
|
608
|
+
// // depthWriteEnabled: true,
|
|
609
|
+
// // depthCompare: 'less',
|
|
610
|
+
// // format: 'depth24plus-stencil8',
|
|
611
|
+
// },
|
|
612
|
+
primitive: {
|
|
613
|
+
cullMode: "back",
|
|
614
|
+
topology: "triangle-list"
|
|
615
|
+
},
|
|
616
|
+
vertex: {
|
|
617
|
+
module: void 0,
|
|
618
|
+
entryPoint: "main"
|
|
619
|
+
},
|
|
620
|
+
fragment: {
|
|
621
|
+
module: void 0,
|
|
622
|
+
entryPoint: "main",
|
|
623
|
+
targets: [
|
|
624
|
+
// { format: props.color0Format || 'bgra8unorm' }
|
|
625
|
+
]
|
|
626
|
+
},
|
|
627
|
+
layout: "auto"
|
|
628
|
+
};
|
|
629
|
+
function applyParametersToRenderPipelineDescriptor(pipelineDescriptor, parameters = {}) {
|
|
630
|
+
Object.assign(pipelineDescriptor, { ...DEFAULT_PIPELINE_DESCRIPTOR, ...pipelineDescriptor });
|
|
631
|
+
setParameters(pipelineDescriptor, parameters);
|
|
632
|
+
}
|
|
633
|
+
function setParameters(pipelineDescriptor, parameters) {
|
|
634
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
635
|
+
const setterFunction = PARAMETER_TABLE[key];
|
|
636
|
+
if (!setterFunction) {
|
|
637
|
+
throw new Error(`Illegal parameter ${key}`);
|
|
638
|
+
}
|
|
639
|
+
setterFunction(key, value, pipelineDescriptor);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
function addColorState(descriptor) {
|
|
643
|
+
descriptor.fragment.targets = descriptor.fragment?.targets || [];
|
|
644
|
+
if (!Array.isArray(descriptor.fragment?.targets)) {
|
|
645
|
+
throw new Error("colorstate");
|
|
646
|
+
}
|
|
647
|
+
if (descriptor.fragment?.targets?.length === 0) {
|
|
648
|
+
descriptor.fragment.targets?.push({});
|
|
649
|
+
}
|
|
650
|
+
return descriptor.fragment?.targets;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/adapter/helpers/get-bind-group.ts
|
|
654
|
+
var import_core7 = __toESM(require_core(), 1);
|
|
655
|
+
function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
|
|
656
|
+
const entries = getBindGroupEntries(bindings, shaderLayout);
|
|
657
|
+
return device.createBindGroup({
|
|
658
|
+
layout: bindGroupLayout,
|
|
659
|
+
entries
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
function getShaderLayoutBinding(shaderLayout, bindingName) {
|
|
663
|
+
const bindingLayout = shaderLayout.bindings.find(
|
|
664
|
+
(binding) => binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase()
|
|
665
|
+
);
|
|
666
|
+
if (!bindingLayout) {
|
|
667
|
+
import_core7.log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
668
|
+
}
|
|
669
|
+
return bindingLayout;
|
|
670
|
+
}
|
|
671
|
+
function getBindGroupEntries(bindings, shaderLayout) {
|
|
672
|
+
const entries = [];
|
|
673
|
+
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
674
|
+
const bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
|
|
675
|
+
if (bindingLayout) {
|
|
676
|
+
entries.push(getBindGroupEntry(value, bindingLayout.location));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return entries;
|
|
680
|
+
}
|
|
681
|
+
function getBindGroupEntry(binding, index) {
|
|
682
|
+
if (binding instanceof import_core7.Buffer) {
|
|
683
|
+
return {
|
|
684
|
+
binding: index,
|
|
685
|
+
resource: {
|
|
686
|
+
buffer: (0, import_core7.cast)(binding).handle
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
if (binding instanceof import_core7.Sampler) {
|
|
691
|
+
return {
|
|
692
|
+
binding: index,
|
|
693
|
+
resource: (0, import_core7.cast)(binding).handle
|
|
694
|
+
};
|
|
695
|
+
} else if (binding instanceof import_core7.Texture) {
|
|
696
|
+
return {
|
|
697
|
+
binding: index,
|
|
698
|
+
resource: (0, import_core7.cast)(binding).handle.createView({ label: "bind-group-auto-created" })
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
throw new Error("invalid binding");
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// src/adapter/helpers/get-vertex-buffer-layout.ts
|
|
705
|
+
var import_core8 = __toESM(require_core(), 1);
|
|
706
|
+
function getWebGPUVertexFormat(format) {
|
|
707
|
+
if (format.endsWith("-webgl")) {
|
|
708
|
+
throw new Error(`WebGPU does not support vertex format ${format}`);
|
|
709
|
+
}
|
|
710
|
+
return format;
|
|
711
|
+
}
|
|
712
|
+
function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
713
|
+
const vertexBufferLayouts = [];
|
|
714
|
+
const usedAttributes = /* @__PURE__ */ new Set();
|
|
715
|
+
for (const mapping of bufferLayout) {
|
|
716
|
+
const vertexAttributes = [];
|
|
717
|
+
let stepMode = "vertex";
|
|
718
|
+
let byteStride = 0;
|
|
719
|
+
if (mapping.attributes) {
|
|
720
|
+
for (const attributeMapping of mapping.attributes) {
|
|
721
|
+
const attributeName = attributeMapping.attribute;
|
|
722
|
+
const attributeLayout = findAttributeLayout(shaderLayout, attributeName, usedAttributes);
|
|
723
|
+
stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith("instance") ? "instance" : "vertex");
|
|
724
|
+
vertexAttributes.push({
|
|
725
|
+
format: getWebGPUVertexFormat(attributeMapping.format || mapping.format),
|
|
726
|
+
offset: attributeMapping.byteOffset,
|
|
727
|
+
shaderLocation: attributeLayout.location
|
|
728
|
+
});
|
|
729
|
+
byteStride += (0, import_core8.decodeVertexFormat)(mapping.format).byteLength;
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
const attributeLayout = findAttributeLayout(shaderLayout, mapping.name, usedAttributes);
|
|
733
|
+
if (!attributeLayout) {
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
byteStride = (0, import_core8.decodeVertexFormat)(mapping.format).byteLength;
|
|
737
|
+
stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith("instance") ? "instance" : "vertex");
|
|
738
|
+
vertexAttributes.push({
|
|
739
|
+
format: getWebGPUVertexFormat(mapping.format),
|
|
740
|
+
// We only support 0 offset for non-interleaved buffer layouts
|
|
741
|
+
offset: 0,
|
|
742
|
+
shaderLocation: attributeLayout.location
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
vertexBufferLayouts.push({
|
|
746
|
+
arrayStride: mapping.byteStride || byteStride,
|
|
747
|
+
stepMode,
|
|
748
|
+
attributes: vertexAttributes
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
for (const attribute of shaderLayout.attributes) {
|
|
752
|
+
if (!usedAttributes.has(attribute.name)) {
|
|
753
|
+
vertexBufferLayouts.push({
|
|
754
|
+
arrayStride: (0, import_core8.decodeVertexFormat)("float32x3").byteLength,
|
|
755
|
+
stepMode: attribute.stepMode || (attribute.name.startsWith("instance") ? "instance" : "vertex"),
|
|
756
|
+
attributes: [
|
|
757
|
+
{
|
|
758
|
+
format: getWebGPUVertexFormat("float32x3"),
|
|
759
|
+
offset: 0,
|
|
760
|
+
shaderLocation: attribute.location
|
|
761
|
+
}
|
|
762
|
+
]
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return vertexBufferLayouts;
|
|
767
|
+
}
|
|
768
|
+
function findAttributeLayout(shaderLayout, name, attributeNames) {
|
|
769
|
+
const attribute = shaderLayout.attributes.find((attribute2) => attribute2.name === name);
|
|
770
|
+
if (!attribute) {
|
|
771
|
+
import_core8.log.warn(`Unknown attribute ${name}`)();
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
if (attributeNames.has(name)) {
|
|
775
|
+
throw new Error(`Duplicate attribute ${name}`);
|
|
776
|
+
}
|
|
777
|
+
attributeNames.add(name);
|
|
778
|
+
return attribute;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
782
|
+
var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
|
|
783
|
+
device;
|
|
784
|
+
handle;
|
|
785
|
+
vs;
|
|
786
|
+
fs = null;
|
|
787
|
+
/** For internal use to create BindGroups */
|
|
788
|
+
_bindings;
|
|
789
|
+
_bindGroupLayout = null;
|
|
790
|
+
_bindGroup = null;
|
|
791
|
+
constructor(device, props) {
|
|
792
|
+
super(device, props);
|
|
793
|
+
this.device = device;
|
|
794
|
+
this.handle = this.props.handle;
|
|
795
|
+
if (!this.handle) {
|
|
796
|
+
const descriptor = this._getRenderPipelineDescriptor();
|
|
797
|
+
import_core9.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
|
|
798
|
+
import_core9.log.probe(1, JSON.stringify(descriptor, null, 2))();
|
|
799
|
+
import_core9.log.groupEnd(1)();
|
|
800
|
+
this.handle = this.device.handle.createRenderPipeline(descriptor);
|
|
801
|
+
}
|
|
802
|
+
this.handle.label = this.props.id;
|
|
803
|
+
this.vs = (0, import_core9.cast)(props.vs);
|
|
804
|
+
this.fs = (0, import_core9.cast)(props.fs);
|
|
805
|
+
this._bindings = { ...this.props.bindings };
|
|
806
|
+
}
|
|
807
|
+
destroy() {
|
|
808
|
+
this.handle = null;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* @todo Use renderpass.setBindings() ?
|
|
812
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
813
|
+
*/
|
|
814
|
+
setBindings(bindings) {
|
|
815
|
+
Object.assign(this._bindings, bindings);
|
|
816
|
+
}
|
|
817
|
+
/** @todo - should this be moved to renderpass? */
|
|
818
|
+
draw(options) {
|
|
819
|
+
const webgpuRenderPass = options.renderPass;
|
|
820
|
+
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
821
|
+
const bindGroup = this._getBindGroup();
|
|
822
|
+
if (bindGroup) {
|
|
823
|
+
webgpuRenderPass.handle.setBindGroup(0, bindGroup);
|
|
824
|
+
}
|
|
825
|
+
options.vertexArray.bindBeforeRender(options.renderPass);
|
|
826
|
+
if (options.indexCount) {
|
|
827
|
+
webgpuRenderPass.handle.drawIndexed(
|
|
828
|
+
options.indexCount,
|
|
829
|
+
options.instanceCount,
|
|
830
|
+
options.firstIndex,
|
|
831
|
+
options.baseVertex,
|
|
832
|
+
options.firstInstance
|
|
833
|
+
);
|
|
834
|
+
} else {
|
|
835
|
+
webgpuRenderPass.handle.draw(
|
|
836
|
+
options.vertexCount || 0,
|
|
837
|
+
options.instanceCount || 1,
|
|
838
|
+
// If 0, nothing will be drawn
|
|
839
|
+
options.firstInstance
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
843
|
+
return true;
|
|
844
|
+
}
|
|
845
|
+
/** Return a bind group created by setBindings */
|
|
846
|
+
_getBindGroup() {
|
|
847
|
+
if (this.props.shaderLayout.bindings.length === 0) {
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
851
|
+
this._bindGroup = this._bindGroup || getBindGroup(
|
|
852
|
+
this.device.handle,
|
|
853
|
+
this._bindGroupLayout,
|
|
854
|
+
this.props.shaderLayout,
|
|
855
|
+
this._bindings
|
|
856
|
+
);
|
|
857
|
+
return this._bindGroup;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
861
|
+
*/
|
|
862
|
+
_getRenderPipelineDescriptor() {
|
|
863
|
+
const vertex = {
|
|
864
|
+
module: (0, import_core9.cast)(this.props.vs).handle,
|
|
865
|
+
entryPoint: this.props.vertexEntryPoint || "main",
|
|
866
|
+
buffers: getVertexBufferLayout(this.props.shaderLayout, this.props.bufferLayout)
|
|
867
|
+
};
|
|
868
|
+
const fragment = {
|
|
869
|
+
module: (0, import_core9.cast)(this.props.fs).handle,
|
|
870
|
+
entryPoint: this.props.fragmentEntryPoint || "main",
|
|
871
|
+
targets: [
|
|
872
|
+
{
|
|
873
|
+
// TODO exclamation mark hack!
|
|
874
|
+
format: getWebGPUTextureFormat(this.device?.canvasContext?.format)
|
|
875
|
+
}
|
|
876
|
+
]
|
|
877
|
+
};
|
|
878
|
+
switch (this.props.topology) {
|
|
879
|
+
case "triangle-fan-webgl":
|
|
880
|
+
case "line-loop-webgl":
|
|
881
|
+
throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);
|
|
882
|
+
default:
|
|
883
|
+
}
|
|
884
|
+
const descriptor = {
|
|
885
|
+
vertex,
|
|
886
|
+
fragment,
|
|
887
|
+
primitive: {
|
|
888
|
+
topology: this.props.topology
|
|
889
|
+
},
|
|
890
|
+
layout: "auto"
|
|
891
|
+
};
|
|
892
|
+
applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
|
|
893
|
+
return descriptor;
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// src/adapter/resources/webgpu-framebuffer.ts
|
|
898
|
+
var import_core10 = __toESM(require_core(), 1);
|
|
899
|
+
var WebGPUFramebuffer = class extends import_core10.Framebuffer {
|
|
900
|
+
device;
|
|
901
|
+
constructor(device, props) {
|
|
902
|
+
super(device, props);
|
|
903
|
+
this.device = device;
|
|
904
|
+
this.autoCreateAttachmentTextures();
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
// src/adapter/resources/webgpu-compute-pipeline.ts
|
|
909
|
+
var import_core11 = __toESM(require_core(), 1);
|
|
910
|
+
var WebGPUComputePipeline = class extends import_core11.ComputePipeline {
|
|
911
|
+
device;
|
|
912
|
+
handle;
|
|
913
|
+
/** For internal use to create BindGroups */
|
|
914
|
+
_bindGroupLayout = null;
|
|
915
|
+
_bindGroup = null;
|
|
916
|
+
/** For internal use to create BindGroups */
|
|
917
|
+
_bindings = {};
|
|
918
|
+
constructor(device, props) {
|
|
919
|
+
super(device, props);
|
|
920
|
+
this.device = device;
|
|
921
|
+
const webgpuShader = this.props.shader;
|
|
922
|
+
this.handle = this.props.handle || this.device.handle.createComputePipeline({
|
|
923
|
+
label: this.props.id,
|
|
924
|
+
compute: {
|
|
925
|
+
module: webgpuShader.handle,
|
|
926
|
+
entryPoint: this.props.entryPoint,
|
|
927
|
+
constants: this.props.constants
|
|
928
|
+
},
|
|
929
|
+
layout: "auto"
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* @todo Use renderpass.setBindings() ?
|
|
934
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
935
|
+
*/
|
|
936
|
+
setBindings(bindings) {
|
|
937
|
+
Object.assign(this._bindings, bindings);
|
|
938
|
+
}
|
|
939
|
+
/** Return a bind group created by setBindings */
|
|
940
|
+
_getBindGroup() {
|
|
941
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
942
|
+
this._bindGroup = this._bindGroup || getBindGroup(
|
|
943
|
+
this.device.handle,
|
|
944
|
+
this._bindGroupLayout,
|
|
945
|
+
this.props.shaderLayout,
|
|
946
|
+
this._bindings
|
|
947
|
+
);
|
|
948
|
+
return this._bindGroup;
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
// src/adapter/resources/webgpu-render-pass.ts
|
|
953
|
+
var import_core12 = __toESM(require_core(), 1);
|
|
954
|
+
var WebGPURenderPass = class extends import_core12.RenderPass {
|
|
955
|
+
device;
|
|
956
|
+
handle;
|
|
957
|
+
/** Active pipeline */
|
|
958
|
+
pipeline = null;
|
|
959
|
+
constructor(device, props = {}) {
|
|
960
|
+
super(device, props);
|
|
961
|
+
this.device = device;
|
|
962
|
+
const framebuffer = props.framebuffer || device.canvasContext.getCurrentFramebuffer();
|
|
963
|
+
const renderPassDescriptor = this.getRenderPassDescriptor(framebuffer);
|
|
964
|
+
const webgpuQuerySet = props.timestampQuerySet;
|
|
965
|
+
if (webgpuQuerySet) {
|
|
966
|
+
renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
|
|
967
|
+
}
|
|
968
|
+
if (device.features.has("timestamp-query")) {
|
|
969
|
+
const webgpuQuerySet2 = props.timestampQuerySet;
|
|
970
|
+
renderPassDescriptor.timestampWrites = webgpuQuerySet2 ? {
|
|
971
|
+
querySet: webgpuQuerySet2.handle,
|
|
972
|
+
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
973
|
+
endOfPassWriteIndex: props.endTimestampIndex
|
|
974
|
+
} : void 0;
|
|
975
|
+
}
|
|
976
|
+
this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
977
|
+
this.handle.label = this.props.id;
|
|
978
|
+
import_core12.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
|
|
979
|
+
import_core12.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
|
|
980
|
+
import_core12.log.groupEnd(3)();
|
|
981
|
+
}
|
|
982
|
+
destroy() {
|
|
983
|
+
}
|
|
984
|
+
end() {
|
|
985
|
+
this.handle.end();
|
|
986
|
+
}
|
|
987
|
+
setPipeline(pipeline) {
|
|
988
|
+
this.pipeline = (0, import_core12.cast)(pipeline);
|
|
989
|
+
this.handle.setPipeline(this.pipeline.handle);
|
|
990
|
+
}
|
|
991
|
+
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
992
|
+
setBindings(bindings) {
|
|
993
|
+
this.pipeline?.setBindings(bindings);
|
|
994
|
+
const bindGroup = this.pipeline?._getBindGroup();
|
|
995
|
+
if (bindGroup) {
|
|
996
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
setIndexBuffer(buffer, indexFormat, offset = 0, size) {
|
|
1000
|
+
this.handle.setIndexBuffer((0, import_core12.cast)(buffer).handle, indexFormat, offset, size);
|
|
1001
|
+
}
|
|
1002
|
+
setVertexBuffer(slot, buffer, offset = 0) {
|
|
1003
|
+
this.handle.setVertexBuffer(slot, (0, import_core12.cast)(buffer).handle, offset);
|
|
1004
|
+
}
|
|
1005
|
+
draw(options) {
|
|
1006
|
+
if (options.indexCount) {
|
|
1007
|
+
this.handle.drawIndexed(
|
|
1008
|
+
options.indexCount,
|
|
1009
|
+
options.instanceCount,
|
|
1010
|
+
options.firstIndex,
|
|
1011
|
+
options.baseVertex,
|
|
1012
|
+
options.firstInstance
|
|
1013
|
+
);
|
|
1014
|
+
} else {
|
|
1015
|
+
this.handle.draw(
|
|
1016
|
+
options.vertexCount || 0,
|
|
1017
|
+
options.instanceCount || 1,
|
|
1018
|
+
options.firstIndex,
|
|
1019
|
+
options.firstInstance
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
drawIndirect() {
|
|
1024
|
+
}
|
|
1025
|
+
setParameters(parameters) {
|
|
1026
|
+
const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
|
|
1027
|
+
if (blendConstant) {
|
|
1028
|
+
this.handle.setBlendConstant(blendConstant);
|
|
1029
|
+
}
|
|
1030
|
+
if (stencilReference) {
|
|
1031
|
+
this.handle.setStencilReference(stencilReference);
|
|
1032
|
+
}
|
|
1033
|
+
if (scissorRect) {
|
|
1034
|
+
this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
|
|
1035
|
+
}
|
|
1036
|
+
if (viewport) {
|
|
1037
|
+
this.handle.setViewport(
|
|
1038
|
+
viewport[0],
|
|
1039
|
+
viewport[1],
|
|
1040
|
+
viewport[2],
|
|
1041
|
+
viewport[3],
|
|
1042
|
+
viewport[4],
|
|
1043
|
+
viewport[5]
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
pushDebugGroup(groupLabel) {
|
|
1048
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1049
|
+
}
|
|
1050
|
+
popDebugGroup() {
|
|
1051
|
+
this.handle.popDebugGroup();
|
|
1052
|
+
}
|
|
1053
|
+
insertDebugMarker(markerLabel) {
|
|
1054
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1055
|
+
}
|
|
1056
|
+
beginOcclusionQuery(queryIndex) {
|
|
1057
|
+
this.handle.beginOcclusionQuery(queryIndex);
|
|
1058
|
+
}
|
|
1059
|
+
endOcclusionQuery() {
|
|
1060
|
+
this.handle.endOcclusionQuery();
|
|
1061
|
+
}
|
|
1062
|
+
// executeBundles(bundles: Iterable<GPURenderBundle>): void;
|
|
1063
|
+
// INTERNAL
|
|
1064
|
+
/**
|
|
1065
|
+
* Partial render pass descriptor. Used by WebGPURenderPass.
|
|
1066
|
+
* @returns attachments fields of a renderpass descriptor.
|
|
1067
|
+
*/
|
|
1068
|
+
getRenderPassDescriptor(framebuffer) {
|
|
1069
|
+
const renderPassDescriptor = {
|
|
1070
|
+
colorAttachments: []
|
|
1071
|
+
};
|
|
1072
|
+
renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map((colorAttachment) => ({
|
|
1073
|
+
// clear values
|
|
1074
|
+
loadOp: this.props.clearColor !== false ? "clear" : "load",
|
|
1075
|
+
colorClearValue: this.props.clearColor || [0, 0, 0, 0],
|
|
1076
|
+
storeOp: this.props.discard ? "discard" : "store",
|
|
1077
|
+
// ...colorAttachment,
|
|
1078
|
+
view: colorAttachment.handle
|
|
1079
|
+
}));
|
|
1080
|
+
if (framebuffer.depthStencilAttachment) {
|
|
1081
|
+
renderPassDescriptor.depthStencilAttachment = {
|
|
1082
|
+
view: framebuffer.depthStencilAttachment.handle
|
|
1083
|
+
};
|
|
1084
|
+
const { depthStencilAttachment } = renderPassDescriptor;
|
|
1085
|
+
if (this.props.depthReadOnly) {
|
|
1086
|
+
depthStencilAttachment.depthReadOnly = true;
|
|
1087
|
+
}
|
|
1088
|
+
depthStencilAttachment.depthClearValue = this.props.clearDepth || 0;
|
|
1089
|
+
const hasDepthAspect = true;
|
|
1090
|
+
if (hasDepthAspect) {
|
|
1091
|
+
depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
|
|
1092
|
+
depthStencilAttachment.depthStoreOp = "store";
|
|
1093
|
+
}
|
|
1094
|
+
const hasStencilAspect = false;
|
|
1095
|
+
if (hasStencilAspect) {
|
|
1096
|
+
depthStencilAttachment.stencilLoadOp = this.props.clearStencil !== false ? "clear" : "load";
|
|
1097
|
+
depthStencilAttachment.stencilStoreOp = "store";
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
return renderPassDescriptor;
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
// src/adapter/resources/webgpu-compute-pass.ts
|
|
1105
|
+
var import_core13 = __toESM(require_core(), 1);
|
|
1106
|
+
var WebGPUComputePass = class extends import_core13.ComputePass {
|
|
1107
|
+
device;
|
|
1108
|
+
handle;
|
|
1109
|
+
_webgpuPipeline = null;
|
|
1110
|
+
constructor(device, props) {
|
|
1111
|
+
super(device, props);
|
|
1112
|
+
this.device = device;
|
|
1113
|
+
let timestampWrites;
|
|
1114
|
+
if (device.features.has("timestamp-query")) {
|
|
1115
|
+
const webgpuQuerySet = props.timestampQuerySet;
|
|
1116
|
+
if (webgpuQuerySet) {
|
|
1117
|
+
timestampWrites = {
|
|
1118
|
+
querySet: webgpuQuerySet.handle,
|
|
1119
|
+
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
1120
|
+
endOfPassWriteIndex: props.endTimestampIndex
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
this.handle = this.props.handle || device.commandEncoder?.beginComputePass({
|
|
1125
|
+
label: this.props.id,
|
|
1126
|
+
timestampWrites
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
/** @note no WebGPU destroy method, just gc */
|
|
1130
|
+
destroy() {
|
|
1131
|
+
}
|
|
1132
|
+
end() {
|
|
1133
|
+
this.handle.end();
|
|
1134
|
+
}
|
|
1135
|
+
setPipeline(pipeline) {
|
|
1136
|
+
const wgpuPipeline = pipeline;
|
|
1137
|
+
this.handle.setPipeline(wgpuPipeline.handle);
|
|
1138
|
+
this._webgpuPipeline = wgpuPipeline;
|
|
1139
|
+
this.setBindings([]);
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Sets an array of bindings (uniform buffers, samplers, textures, ...)
|
|
1143
|
+
* TODO - still some API confusion - does this method go here or on the pipeline?
|
|
1144
|
+
*/
|
|
1145
|
+
setBindings(bindings) {
|
|
1146
|
+
const bindGroup = this._webgpuPipeline._getBindGroup();
|
|
1147
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1151
|
+
* @param x X dimension of the grid of work groups to dispatch.
|
|
1152
|
+
* @param y Y dimension of the grid of work groups to dispatch.
|
|
1153
|
+
* @param z Z dimension of the grid of work groups to dispatch.
|
|
1154
|
+
*/
|
|
1155
|
+
dispatch(x, y, z) {
|
|
1156
|
+
this.handle.dispatchWorkgroups(x, y, z);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1160
|
+
*
|
|
1161
|
+
* 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()
|
|
1162
|
+
* @param indirectBuffer
|
|
1163
|
+
* @param indirectOffset offset in buffer to the beginning of the dispatch data.
|
|
1164
|
+
*/
|
|
1165
|
+
dispatchIndirect(indirectBuffer, indirectByteOffset = 0) {
|
|
1166
|
+
const webgpuBuffer = indirectBuffer;
|
|
1167
|
+
this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
|
|
1168
|
+
}
|
|
1169
|
+
pushDebugGroup(groupLabel) {
|
|
1170
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1171
|
+
}
|
|
1172
|
+
popDebugGroup() {
|
|
1173
|
+
this.handle.popDebugGroup();
|
|
1174
|
+
}
|
|
1175
|
+
insertDebugMarker(markerLabel) {
|
|
1176
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
// src/adapter/resources/webgpu-vertex-array.ts
|
|
1181
|
+
var import_core14 = __toESM(require_core(), 1);
|
|
1182
|
+
|
|
1183
|
+
// ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
|
|
1184
|
+
function isElectron(mockUserAgent) {
|
|
1185
|
+
if (typeof window !== "undefined" && typeof window.process === "object" && // @ts-expect-error
|
|
1186
|
+
window.process.type === "renderer") {
|
|
1187
|
+
return true;
|
|
1188
|
+
}
|
|
1189
|
+
if (typeof process !== "undefined" && typeof process.versions === "object" && // eslint-disable-next-line
|
|
1190
|
+
Boolean(process.versions["electron"])) {
|
|
1191
|
+
return true;
|
|
1192
|
+
}
|
|
1193
|
+
const realUserAgent = typeof navigator === "object" && typeof navigator.userAgent === "string" && navigator.userAgent;
|
|
1194
|
+
const userAgent = mockUserAgent || realUserAgent;
|
|
1195
|
+
if (userAgent && userAgent.indexOf("Electron") >= 0) {
|
|
1196
|
+
return true;
|
|
1197
|
+
}
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
|
|
1202
|
+
function isBrowser() {
|
|
1203
|
+
const isNode = (
|
|
1204
|
+
// @ts-expect-error
|
|
1205
|
+
typeof process === "object" && String(process) === "[object process]" && !process.browser
|
|
1206
|
+
);
|
|
1207
|
+
return !isNode || isElectron();
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// ../../node_modules/@probe.gl/env/dist/lib/globals.js
|
|
1211
|
+
var self_ = globalThis.self || globalThis.window || globalThis.global;
|
|
1212
|
+
var window_ = globalThis.window || globalThis.self || globalThis.global;
|
|
1213
|
+
var document_ = globalThis.document || {};
|
|
1214
|
+
var process_ = globalThis.process || {};
|
|
1215
|
+
var console_ = globalThis.console;
|
|
1216
|
+
var navigator_ = globalThis.navigator || {};
|
|
1217
|
+
|
|
1218
|
+
// ../../node_modules/@probe.gl/env/dist/lib/get-browser.js
|
|
1219
|
+
var window2 = globalThis;
|
|
1220
|
+
function getBrowser(mockUserAgent) {
|
|
1221
|
+
if (!mockUserAgent && !isBrowser()) {
|
|
1222
|
+
return "Node";
|
|
1223
|
+
}
|
|
1224
|
+
if (isElectron(mockUserAgent)) {
|
|
1225
|
+
return "Electron";
|
|
1226
|
+
}
|
|
1227
|
+
const userAgent = mockUserAgent || navigator_.userAgent || "";
|
|
1228
|
+
if (userAgent.indexOf("Edge") > -1) {
|
|
1229
|
+
return "Edge";
|
|
1230
|
+
}
|
|
1231
|
+
const isMSIE = userAgent.indexOf("MSIE ") !== -1;
|
|
1232
|
+
const isTrident = userAgent.indexOf("Trident/") !== -1;
|
|
1233
|
+
if (isMSIE || isTrident) {
|
|
1234
|
+
return "IE";
|
|
1235
|
+
}
|
|
1236
|
+
if (window2.chrome) {
|
|
1237
|
+
return "Chrome";
|
|
1238
|
+
}
|
|
1239
|
+
if (window2.safari) {
|
|
1240
|
+
return "Safari";
|
|
1241
|
+
}
|
|
1242
|
+
if (window2.mozInnerScreenX) {
|
|
1243
|
+
return "Firefox";
|
|
1244
|
+
}
|
|
1245
|
+
return "Unknown";
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// src/adapter/resources/webgpu-vertex-array.ts
|
|
1249
|
+
var WebGPUVertexArray = class extends import_core14.VertexArray {
|
|
1250
|
+
get [Symbol.toStringTag]() {
|
|
1251
|
+
return "WebGPUVertexArray";
|
|
1252
|
+
}
|
|
1253
|
+
device;
|
|
1254
|
+
/** Vertex Array is a helper class under WebGPU */
|
|
1255
|
+
handle;
|
|
1256
|
+
// Create a VertexArray
|
|
1257
|
+
constructor(device, props) {
|
|
1258
|
+
super(device, props);
|
|
1259
|
+
this.device = device;
|
|
1260
|
+
}
|
|
1261
|
+
destroy() {
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Set an elements buffer, for indexed rendering.
|
|
1265
|
+
* Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
|
|
1266
|
+
*/
|
|
1267
|
+
setIndexBuffer(buffer) {
|
|
1268
|
+
this.indexBuffer = buffer;
|
|
1269
|
+
}
|
|
1270
|
+
/** Set a bufferSlot in vertex attributes array to a buffer, enables the bufferSlot, sets divisor */
|
|
1271
|
+
setBuffer(bufferSlot, buffer) {
|
|
1272
|
+
this.attributes[bufferSlot] = buffer;
|
|
1273
|
+
}
|
|
1274
|
+
bindBeforeRender(renderPass, firstIndex, indexCount) {
|
|
1275
|
+
const webgpuRenderPass = renderPass;
|
|
1276
|
+
const webgpuIndexBuffer = this.indexBuffer;
|
|
1277
|
+
if (webgpuIndexBuffer?.handle) {
|
|
1278
|
+
import_core14.log.warn("setting index buffer", webgpuIndexBuffer?.handle, webgpuIndexBuffer?.indexType)();
|
|
1279
|
+
webgpuRenderPass.handle.setIndexBuffer(
|
|
1280
|
+
webgpuIndexBuffer?.handle,
|
|
1281
|
+
webgpuIndexBuffer?.indexType
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
1284
|
+
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
1285
|
+
const webgpuBuffer = this.attributes[location];
|
|
1286
|
+
if (webgpuBuffer?.handle) {
|
|
1287
|
+
import_core14.log.warn(`setting vertex buffer ${location}`, webgpuBuffer?.handle)();
|
|
1288
|
+
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
unbindAfterRender(renderPass) {
|
|
1293
|
+
}
|
|
1294
|
+
// DEPRECATED METHODS
|
|
1295
|
+
/**
|
|
1296
|
+
* @deprecated is this even an issue for WebGPU?
|
|
1297
|
+
* Attribute 0 can not be disable on most desktop OpenGL based browsers
|
|
1298
|
+
*/
|
|
1299
|
+
static isConstantAttributeZeroSupported(device) {
|
|
1300
|
+
return getBrowser() === "Chrome";
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
|
|
1304
|
+
// src/adapter/webgpu-canvas-context.ts
|
|
1305
|
+
var import_core15 = __toESM(require_core(), 1);
|
|
1306
|
+
var WebGPUCanvasContext = class extends import_core15.CanvasContext {
|
|
1307
|
+
device;
|
|
1308
|
+
gpuCanvasContext;
|
|
1309
|
+
/** Format of returned textures: "bgra8unorm", "rgba8unorm", "rgba16float". */
|
|
1310
|
+
format = navigator.gpu.getPreferredCanvasFormat();
|
|
1311
|
+
/** Default stencil format for depth textures */
|
|
1312
|
+
depthStencilFormat = "depth24plus";
|
|
1313
|
+
depthStencilAttachment = null;
|
|
1314
|
+
constructor(device, adapter, props) {
|
|
1315
|
+
super(props);
|
|
1316
|
+
this.device = device;
|
|
1317
|
+
this.width = -1;
|
|
1318
|
+
this.height = -1;
|
|
1319
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
1320
|
+
this.gpuCanvasContext = this.canvas.getContext("webgpu");
|
|
1321
|
+
this.format = "bgra8unorm";
|
|
1322
|
+
}
|
|
1323
|
+
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
1324
|
+
destroy() {
|
|
1325
|
+
this.gpuCanvasContext.unconfigure();
|
|
1326
|
+
}
|
|
1327
|
+
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
1328
|
+
getCurrentFramebuffer() {
|
|
1329
|
+
this.update();
|
|
1330
|
+
const currentColorAttachment = this.getCurrentTexture();
|
|
1331
|
+
this.width = currentColorAttachment.width;
|
|
1332
|
+
this.height = currentColorAttachment.height;
|
|
1333
|
+
this._createDepthStencilAttachment();
|
|
1334
|
+
return new WebGPUFramebuffer(this.device, {
|
|
1335
|
+
colorAttachments: [currentColorAttachment],
|
|
1336
|
+
depthStencilAttachment: this.depthStencilAttachment
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
/** Resizes and updates render targets if necessary */
|
|
1340
|
+
update() {
|
|
1341
|
+
const [width, height] = this.getPixelSize();
|
|
1342
|
+
const sizeChanged = width !== this.width || height !== this.height;
|
|
1343
|
+
if (sizeChanged) {
|
|
1344
|
+
this.width = width;
|
|
1345
|
+
this.height = height;
|
|
1346
|
+
if (this.depthStencilAttachment) {
|
|
1347
|
+
this.depthStencilAttachment.destroy();
|
|
1348
|
+
this.depthStencilAttachment = null;
|
|
1349
|
+
}
|
|
1350
|
+
this.gpuCanvasContext.configure({
|
|
1351
|
+
device: this.device.handle,
|
|
1352
|
+
format: getWebGPUTextureFormat(this.format),
|
|
1353
|
+
// Can be used to define e.g. -srgb views
|
|
1354
|
+
// viewFormats: [...]
|
|
1355
|
+
colorSpace: this.props.colorSpace,
|
|
1356
|
+
alphaMode: this.props.alphaMode
|
|
1357
|
+
});
|
|
1358
|
+
import_core15.log.log(1, `Resized to ${this.width}x${this.height}px`)();
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
resize(options) {
|
|
1362
|
+
this.update();
|
|
1363
|
+
}
|
|
1364
|
+
/** Wrap the current canvas context texture in a luma.gl texture */
|
|
1365
|
+
getCurrentTexture() {
|
|
1366
|
+
return this.device._createTexture({
|
|
1367
|
+
id: `${this.id}#color-texture`,
|
|
1368
|
+
handle: this.gpuCanvasContext.getCurrentTexture(),
|
|
1369
|
+
format: this.format
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
1373
|
+
_createDepthStencilAttachment() {
|
|
1374
|
+
if (!this.depthStencilAttachment) {
|
|
1375
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
1376
|
+
id: `${this.id}#depth-stencil-texture`,
|
|
1377
|
+
format: this.depthStencilFormat,
|
|
1378
|
+
width: this.width,
|
|
1379
|
+
height: this.height,
|
|
1380
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
return this.depthStencilAttachment;
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
// src/adapter/resources/webgpu-query-set.ts
|
|
1388
|
+
var import_core16 = __toESM(require_core(), 1);
|
|
1389
|
+
var WebGPUQuerySet = class extends import_core16.QuerySet {
|
|
1390
|
+
device;
|
|
1391
|
+
handle;
|
|
1392
|
+
constructor(device, props) {
|
|
1393
|
+
super(device, props);
|
|
1394
|
+
this.device = device;
|
|
1395
|
+
this.handle = this.props.handle || this.device.handle.createQuerySet({
|
|
1396
|
+
type: this.props.type,
|
|
1397
|
+
count: this.props.count
|
|
1398
|
+
});
|
|
1399
|
+
this.handle.label = this.props.id;
|
|
1400
|
+
}
|
|
1401
|
+
destroy() {
|
|
1402
|
+
this.handle?.destroy();
|
|
1403
|
+
this.handle = null;
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
|
|
1407
|
+
// src/adapter/webgpu-device.ts
|
|
1408
|
+
var _WebGPUDevice = class extends import_core17.Device {
|
|
1409
|
+
/** type of this device */
|
|
1410
|
+
type = "webgpu";
|
|
1411
|
+
/** The underlying WebGPU device */
|
|
1412
|
+
handle;
|
|
1413
|
+
/* The underlying WebGPU adapter */
|
|
1414
|
+
adapter;
|
|
1415
|
+
/* The underlying WebGPU adapter's info */
|
|
1416
|
+
adapterInfo;
|
|
1417
|
+
features;
|
|
1418
|
+
info;
|
|
1419
|
+
limits;
|
|
1420
|
+
lost;
|
|
1421
|
+
canvasContext = null;
|
|
1422
|
+
_isLost = false;
|
|
1423
|
+
commandEncoder = null;
|
|
1424
|
+
renderPass = null;
|
|
1425
|
+
/** Check if WebGPU is available */
|
|
1426
|
+
static isSupported() {
|
|
1427
|
+
return Boolean(typeof navigator !== "undefined" && navigator.gpu);
|
|
1428
|
+
}
|
|
1429
|
+
static async create(props) {
|
|
1430
|
+
if (!navigator.gpu) {
|
|
1431
|
+
throw new Error(
|
|
1432
|
+
"WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu"
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
import_core17.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
1436
|
+
const adapter = await navigator.gpu.requestAdapter({
|
|
1437
|
+
powerPreference: "high-performance"
|
|
1438
|
+
// forceSoftware: false
|
|
1439
|
+
});
|
|
1440
|
+
if (!adapter) {
|
|
1441
|
+
throw new Error("Failed to request WebGPU adapter");
|
|
1442
|
+
}
|
|
1443
|
+
const adapterInfo = await adapter.requestAdapterInfo();
|
|
1444
|
+
import_core17.log.probe(2, "Adapter available", adapterInfo)();
|
|
1445
|
+
const requiredFeatures = [];
|
|
1446
|
+
const requiredLimits = {};
|
|
1447
|
+
if (props.requestMaxLimits) {
|
|
1448
|
+
requiredFeatures.push(...Array.from(adapter.features));
|
|
1449
|
+
for (const key in adapter.limits) {
|
|
1450
|
+
requiredLimits[key] = adapter.limits[key];
|
|
1451
|
+
}
|
|
1452
|
+
delete requiredLimits.minSubgroupSize;
|
|
1453
|
+
delete requiredLimits.maxSubgroupSize;
|
|
1454
|
+
}
|
|
1455
|
+
const gpuDevice = await adapter.requestDevice({
|
|
1456
|
+
requiredFeatures,
|
|
1457
|
+
requiredLimits
|
|
1458
|
+
});
|
|
1459
|
+
import_core17.log.probe(1, "GPUDevice available")();
|
|
1460
|
+
if (typeof props.canvas === "string") {
|
|
1461
|
+
await import_core17.CanvasContext.pageLoaded;
|
|
1462
|
+
import_core17.log.probe(1, "DOM is loaded")();
|
|
1463
|
+
}
|
|
1464
|
+
const device = new _WebGPUDevice(gpuDevice, adapter, adapterInfo, props);
|
|
1465
|
+
import_core17.log.probe(
|
|
1466
|
+
1,
|
|
1467
|
+
"Device created. For more info, set chrome://flags/#enable-webgpu-developer-features"
|
|
1468
|
+
)();
|
|
1469
|
+
import_core17.log.table(1, device.info)();
|
|
1470
|
+
import_core17.log.groupEnd(1)();
|
|
1471
|
+
return device;
|
|
1472
|
+
}
|
|
1473
|
+
constructor(device, adapter, adapterInfo, props) {
|
|
1474
|
+
super({ ...props, id: props.id || (0, import_core17.uid)("webgpu-device") });
|
|
1475
|
+
this.handle = device;
|
|
1476
|
+
this.adapter = adapter;
|
|
1477
|
+
this.adapterInfo = adapterInfo;
|
|
1478
|
+
this.info = this._getInfo();
|
|
1479
|
+
this.features = this._getFeatures();
|
|
1480
|
+
this.limits = this.handle.limits;
|
|
1481
|
+
this.lost = new Promise(async (resolve) => {
|
|
1482
|
+
const lostInfo = await this.handle.lost;
|
|
1483
|
+
this._isLost = true;
|
|
1484
|
+
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
1485
|
+
});
|
|
1486
|
+
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, {
|
|
1487
|
+
canvas: props.canvas,
|
|
1488
|
+
height: props.height,
|
|
1489
|
+
width: props.width,
|
|
1490
|
+
container: props.container
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
// TODO
|
|
1494
|
+
// Load the glslang module now so that it is available synchronously when compiling shaders
|
|
1495
|
+
// const {glsl = true} = props;
|
|
1496
|
+
// this.glslang = glsl && await loadGlslangModule();
|
|
1497
|
+
destroy() {
|
|
1498
|
+
this.handle.destroy();
|
|
1499
|
+
}
|
|
1500
|
+
isTextureFormatSupported(format) {
|
|
1501
|
+
return !format.includes("webgl");
|
|
1502
|
+
}
|
|
1503
|
+
/** @todo implement proper check? */
|
|
1504
|
+
isTextureFormatFilterable(format) {
|
|
1505
|
+
return this.isTextureFormatSupported(format) && !format.startsWith("depth") && !format.startsWith("stencil");
|
|
1506
|
+
}
|
|
1507
|
+
/** @todo implement proper check? */
|
|
1508
|
+
isTextureFormatRenderable(format) {
|
|
1509
|
+
return this.isTextureFormatSupported(format);
|
|
1510
|
+
}
|
|
1511
|
+
get isLost() {
|
|
1512
|
+
return this._isLost;
|
|
1513
|
+
}
|
|
1514
|
+
createBuffer(props) {
|
|
1515
|
+
const newProps = this._getBufferProps(props);
|
|
1516
|
+
return new WebGPUBuffer(this, newProps);
|
|
1517
|
+
}
|
|
1518
|
+
_createTexture(props) {
|
|
1519
|
+
return new WebGPUTexture(this, props);
|
|
1520
|
+
}
|
|
1521
|
+
createExternalTexture(props) {
|
|
1522
|
+
return new WebGPUExternalTexture(this, props);
|
|
1523
|
+
}
|
|
1524
|
+
createShader(props) {
|
|
1525
|
+
return new WebGPUShader(this, props);
|
|
1526
|
+
}
|
|
1527
|
+
createSampler(props) {
|
|
1528
|
+
return new WebGPUSampler(this, props);
|
|
1529
|
+
}
|
|
1530
|
+
createRenderPipeline(props) {
|
|
1531
|
+
return new WebGPURenderPipeline(this, props);
|
|
1532
|
+
}
|
|
1533
|
+
createFramebuffer(props) {
|
|
1534
|
+
return new WebGPUFramebuffer(this, props);
|
|
1535
|
+
}
|
|
1536
|
+
createComputePipeline(props) {
|
|
1537
|
+
return new WebGPUComputePipeline(this, props);
|
|
1538
|
+
}
|
|
1539
|
+
createVertexArray(props) {
|
|
1540
|
+
return new WebGPUVertexArray(this, props);
|
|
1541
|
+
}
|
|
1542
|
+
// WebGPU specifics
|
|
1543
|
+
/**
|
|
1544
|
+
* Allows a render pass to begin against a canvas context
|
|
1545
|
+
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1546
|
+
*/
|
|
1547
|
+
beginRenderPass(props) {
|
|
1548
|
+
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1549
|
+
return new WebGPURenderPass(this, props);
|
|
1550
|
+
}
|
|
1551
|
+
beginComputePass(props) {
|
|
1552
|
+
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1553
|
+
return new WebGPUComputePass(this, props);
|
|
1554
|
+
}
|
|
1555
|
+
// createCommandEncoder(props: CommandEncoderProps): WebGPUCommandEncoder {
|
|
1556
|
+
// return new WebGPUCommandEncoder(this, props);
|
|
1557
|
+
// }
|
|
1558
|
+
createTransformFeedback(props) {
|
|
1559
|
+
throw new Error("Transform feedback not supported in WebGPU");
|
|
1560
|
+
}
|
|
1561
|
+
createQuerySet(props) {
|
|
1562
|
+
return new WebGPUQuerySet(this, props);
|
|
1563
|
+
}
|
|
1564
|
+
createCanvasContext(props) {
|
|
1565
|
+
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
1566
|
+
}
|
|
1567
|
+
submit() {
|
|
1568
|
+
const commandBuffer = this.commandEncoder?.finish();
|
|
1569
|
+
if (commandBuffer) {
|
|
1570
|
+
this.handle.queue.submit([commandBuffer]);
|
|
1571
|
+
}
|
|
1572
|
+
this.commandEncoder = null;
|
|
1573
|
+
}
|
|
1574
|
+
// PRIVATE METHODS
|
|
1575
|
+
_getInfo() {
|
|
1576
|
+
const [driver, driverVersion] = (this.adapterInfo.driver || "").split(" Version ");
|
|
1577
|
+
const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
|
|
1578
|
+
const renderer = driver || "";
|
|
1579
|
+
const version = driverVersion || "";
|
|
1580
|
+
const gpu = vendor === "apple" ? "apple" : "unknown";
|
|
1581
|
+
const gpuArchitecture = this.adapterInfo.architecture || "unknown";
|
|
1582
|
+
const gpuBackend = this.adapterInfo.backend || "unknown";
|
|
1583
|
+
const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
|
|
1584
|
+
return {
|
|
1585
|
+
type: "webgpu",
|
|
1586
|
+
vendor,
|
|
1587
|
+
renderer,
|
|
1588
|
+
version,
|
|
1589
|
+
gpu,
|
|
1590
|
+
gpuType,
|
|
1591
|
+
gpuBackend,
|
|
1592
|
+
gpuArchitecture,
|
|
1593
|
+
shadingLanguage: "wgsl",
|
|
1594
|
+
shadingLanguageVersion: 100
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
_getFeatures() {
|
|
1598
|
+
const features = new Set(this.handle.features);
|
|
1599
|
+
if (features.has("depth-clamping")) {
|
|
1600
|
+
features.delete("depth-clamping");
|
|
1601
|
+
features.add("depth-clip-control");
|
|
1602
|
+
}
|
|
1603
|
+
if (features.has("texture-compression-bc")) {
|
|
1604
|
+
features.add("texture-compression-bc5-webgl");
|
|
1605
|
+
}
|
|
1606
|
+
const WEBGPU_ALWAYS_FEATURES = [
|
|
1607
|
+
"timer-query-webgl",
|
|
1608
|
+
"compilation-status-async-webgl",
|
|
1609
|
+
"float32-renderable-webgl",
|
|
1610
|
+
"float16-renderable-webgl",
|
|
1611
|
+
"norm16-renderable-webgl",
|
|
1612
|
+
"texture-filterable-anisotropic-webgl",
|
|
1613
|
+
"shader-noperspective-interpolation-webgl"
|
|
1614
|
+
];
|
|
1615
|
+
for (const feature of WEBGPU_ALWAYS_FEATURES) {
|
|
1616
|
+
features.add(feature);
|
|
1617
|
+
}
|
|
1618
|
+
return new import_core17.DeviceFeatures(Array.from(features), this.props.disabledFeatures);
|
|
1619
|
+
}
|
|
1620
|
+
copyExternalImageToTexture(options) {
|
|
1621
|
+
const {
|
|
1622
|
+
source,
|
|
1623
|
+
sourceX = 0,
|
|
1624
|
+
sourceY = 0,
|
|
1625
|
+
texture,
|
|
1626
|
+
mipLevel = 0,
|
|
1627
|
+
aspect = "all",
|
|
1628
|
+
colorSpace = "display-p3",
|
|
1629
|
+
premultipliedAlpha = false,
|
|
1630
|
+
// destinationX,
|
|
1631
|
+
// destinationY,
|
|
1632
|
+
// desitnationZ,
|
|
1633
|
+
width = texture.width,
|
|
1634
|
+
height = texture.height,
|
|
1635
|
+
depth = 1
|
|
1636
|
+
} = options;
|
|
1637
|
+
const webGpuTexture = texture;
|
|
1638
|
+
this.handle?.queue.copyExternalImageToTexture(
|
|
1639
|
+
// source: GPUImageCopyExternalImage
|
|
1640
|
+
{
|
|
1641
|
+
source,
|
|
1642
|
+
origin: [sourceX, sourceY]
|
|
1643
|
+
},
|
|
1644
|
+
// destination: GPUImageCopyTextureTagged
|
|
1645
|
+
{
|
|
1646
|
+
texture: webGpuTexture.handle,
|
|
1647
|
+
origin: [0, 0, 0],
|
|
1648
|
+
// [x, y, z],
|
|
1649
|
+
mipLevel,
|
|
1650
|
+
aspect,
|
|
1651
|
+
colorSpace,
|
|
1652
|
+
premultipliedAlpha
|
|
1653
|
+
},
|
|
1654
|
+
// copySize: GPUExtent3D
|
|
1655
|
+
[width, height, depth]
|
|
1656
|
+
);
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
var WebGPUDevice = _WebGPUDevice;
|
|
1660
|
+
__publicField(WebGPUDevice, "type", "webgpu");
|
|
1661
|
+
return __toCommonJS(bundle_exports);
|
|
1662
|
+
})();
|
|
1663
|
+
return __exports__;
|
|
1664
|
+
});
|