@luma.gl/webgpu 9.1.9 → 9.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/helpers/accessor-to-format.js +1 -0
- package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
- package/dist/adapter/helpers/get-bind-group.d.ts +3 -1
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +28 -10
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +5 -5
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +89 -75
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +13 -16
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +132 -93
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.d.ts +10 -0
- package/dist/adapter/resources/webgpu-command-buffer.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-command-buffer.js +18 -0
- package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -0
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +12 -5
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +28 -5
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +2 -2
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.d.ts +2 -2
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +3 -2
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +1 -0
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts +2 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +5 -2
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +11 -6
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +5 -4
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +33 -20
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +1 -1
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +7 -8
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.js +15 -10
- package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +4 -37
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +97 -126
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.d.ts +2 -2
- package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js +2 -2
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
- package/dist/adapter/webgpu-adapter.d.ts +2 -3
- package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
- package/dist/adapter/webgpu-adapter.js +54 -43
- package/dist/adapter/webgpu-adapter.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +7 -15
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +50 -72
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +16 -27
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +48 -65
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/dist.dev.js +1919 -1520
- package/dist/dist.min.js +6 -5
- package/dist/index.cjs +1749 -1397
- package/dist/index.cjs.map +4 -4
- package/package.json +3 -3
- package/src/adapter/helpers/get-bind-group.ts +31 -11
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +5 -5
- package/src/adapter/helpers/webgpu-parameters.ts +114 -102
- package/src/adapter/resources/webgpu-buffer.ts +163 -102
- package/src/adapter/resources/webgpu-command-buffer.ts +24 -0
- package/src/adapter/resources/webgpu-command-encoder.ts +34 -4
- package/src/adapter/resources/webgpu-compute-pass.ts +1 -1
- package/src/adapter/resources/webgpu-compute-pipeline.ts +2 -2
- package/src/adapter/resources/webgpu-external-texture.ts +2 -2
- package/src/adapter/resources/webgpu-framebuffer.ts +3 -2
- package/src/adapter/resources/webgpu-pipeline-layout.ts +8 -3
- package/src/adapter/resources/webgpu-render-pass.ts +11 -6
- package/src/adapter/resources/webgpu-render-pipeline.ts +39 -24
- package/src/adapter/resources/webgpu-sampler.ts +1 -1
- package/src/adapter/resources/webgpu-shader.ts +11 -8
- package/src/adapter/resources/webgpu-texture-view.ts +14 -8
- package/src/adapter/resources/webgpu-texture.ts +106 -186
- package/src/adapter/resources/webgpu-vertex-array.ts +2 -2
- package/src/adapter/webgpu-adapter.ts +72 -58
- package/src/adapter/webgpu-canvas-context.ts +62 -82
- package/src/adapter/webgpu-device.ts +66 -105
package/dist/dist.dev.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
else if (typeof define === 'function' && define.amd) define([], factory);
|
|
5
5
|
else if (typeof exports === 'object') exports['luma'] = factory();
|
|
6
6
|
else root['luma'] = factory();})(globalThis, function () {
|
|
7
|
+
"use strict";
|
|
7
8
|
var __exports__ = (() => {
|
|
8
9
|
var __create = Object.create;
|
|
9
10
|
var __defProp = Object.defineProperty;
|
|
@@ -11,12 +12,15 @@ var __exports__ = (() => {
|
|
|
11
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
13
|
var __getProtoOf = Object.getPrototypeOf;
|
|
13
14
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
15
|
+
var __esm = (fn, res) => function __init() {
|
|
16
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
17
|
+
};
|
|
14
18
|
var __commonJS = (cb, mod) => function __require() {
|
|
15
19
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
20
|
};
|
|
17
21
|
var __export = (target, all) => {
|
|
18
|
-
for (var
|
|
19
|
-
__defProp(target,
|
|
22
|
+
for (var name2 in all)
|
|
23
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
20
24
|
};
|
|
21
25
|
var __copyProps = (to, from, except, desc) => {
|
|
22
26
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -44,99 +48,168 @@ var __exports__ = (() => {
|
|
|
44
48
|
}
|
|
45
49
|
});
|
|
46
50
|
|
|
47
|
-
// bundle.ts
|
|
48
|
-
var bundle_exports = {};
|
|
49
|
-
__export(bundle_exports, {
|
|
50
|
-
WebGPUBuffer: () => WebGPUBuffer,
|
|
51
|
-
WebGPUDevice: () => WebGPUDevice,
|
|
52
|
-
WebGPUSampler: () => WebGPUSampler,
|
|
53
|
-
WebGPUShader: () => WebGPUShader,
|
|
54
|
-
WebGPUTexture: () => WebGPUTexture,
|
|
55
|
-
webgpuAdapter: () => webgpuAdapter
|
|
56
|
-
});
|
|
57
|
-
__reExport(bundle_exports, __toESM(require_core(), 1));
|
|
58
|
-
|
|
59
|
-
// src/adapter/webgpu-adapter.ts
|
|
60
|
-
var import_core20 = __toESM(require_core(), 1);
|
|
61
|
-
|
|
62
|
-
// src/adapter/webgpu-device.ts
|
|
63
|
-
var import_core19 = __toESM(require_core(), 1);
|
|
64
|
-
|
|
65
51
|
// src/adapter/resources/webgpu-buffer.ts
|
|
66
|
-
var import_core
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
52
|
+
var import_core, WebGPUBuffer;
|
|
53
|
+
var init_webgpu_buffer = __esm({
|
|
54
|
+
"src/adapter/resources/webgpu-buffer.ts"() {
|
|
55
|
+
"use strict";
|
|
56
|
+
import_core = __toESM(require_core(), 1);
|
|
57
|
+
WebGPUBuffer = class extends import_core.Buffer {
|
|
58
|
+
device;
|
|
59
|
+
handle;
|
|
60
|
+
byteLength;
|
|
61
|
+
constructor(device, props) {
|
|
62
|
+
super(device, props);
|
|
63
|
+
this.device = device;
|
|
64
|
+
this.byteLength = props.byteLength || props.data?.byteLength || 0;
|
|
65
|
+
const mappedAtCreation = Boolean(this.props.onMapped || props.data);
|
|
66
|
+
const size = Math.ceil(this.byteLength / 4) * 4;
|
|
67
|
+
this.device.pushErrorScope("out-of-memory");
|
|
68
|
+
this.device.pushErrorScope("validation");
|
|
69
|
+
this.handle = this.props.handle || this.device.handle.createBuffer({
|
|
70
|
+
label: this.props.id,
|
|
71
|
+
// usage defaults to vertex
|
|
72
|
+
usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
73
|
+
mappedAtCreation,
|
|
74
|
+
size
|
|
75
|
+
});
|
|
76
|
+
this.device.popErrorScope((error) => {
|
|
77
|
+
this.device.reportError(new Error(`${this} creation failed ${error.message}`), this)();
|
|
78
|
+
this.device.debug();
|
|
79
|
+
});
|
|
80
|
+
this.device.popErrorScope((error) => {
|
|
81
|
+
this.device.reportError(new Error(`${this} out of memory: ${error.message}`), this)();
|
|
82
|
+
this.device.debug();
|
|
83
|
+
});
|
|
84
|
+
this.device.pushErrorScope("validation");
|
|
85
|
+
if (props.data || props.onMapped) {
|
|
86
|
+
try {
|
|
87
|
+
const arrayBuffer = this.handle.getMappedRange();
|
|
88
|
+
if (props.data) {
|
|
89
|
+
const typedArray = props.data;
|
|
90
|
+
new typedArray.constructor(arrayBuffer).set(typedArray);
|
|
91
|
+
} else {
|
|
92
|
+
props.onMapped?.(arrayBuffer, "mapped");
|
|
93
|
+
}
|
|
94
|
+
} finally {
|
|
95
|
+
this.handle.unmap();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
this.device.popErrorScope((error) => {
|
|
99
|
+
this.device.reportError(new Error(`${this} creation failed ${error.message}`), this)();
|
|
100
|
+
this.device.debug();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
destroy() {
|
|
104
|
+
this.handle?.destroy();
|
|
105
|
+
this.handle = null;
|
|
106
|
+
}
|
|
107
|
+
write(data, byteOffset = 0) {
|
|
108
|
+
const arrayBuffer = ArrayBuffer.isView(data) ? data.buffer : data;
|
|
109
|
+
const dataByteOffset = ArrayBuffer.isView(data) ? data.byteOffset : 0;
|
|
110
|
+
this.device.pushErrorScope("validation");
|
|
111
|
+
this.device.handle.queue.writeBuffer(
|
|
112
|
+
this.handle,
|
|
113
|
+
byteOffset,
|
|
114
|
+
arrayBuffer,
|
|
115
|
+
dataByteOffset,
|
|
116
|
+
data.byteLength
|
|
117
|
+
);
|
|
118
|
+
this.device.popErrorScope((error) => {
|
|
119
|
+
this.device.reportError(new Error(`${this}.write() ${error.message}`), this)();
|
|
120
|
+
this.device.debug();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async mapAndWriteAsync(callback, byteOffset = 0, byteLength = this.byteLength - byteOffset) {
|
|
124
|
+
const isMappable = (this.usage & import_core.Buffer.MAP_WRITE) !== 0;
|
|
125
|
+
const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_WRITE | import_core.Buffer.COPY_SRC, 0, this.byteLength) : null;
|
|
126
|
+
const writeBuffer = mappableBuffer || this;
|
|
127
|
+
this.device.pushErrorScope("validation");
|
|
128
|
+
try {
|
|
129
|
+
await this.device.handle.queue.onSubmittedWorkDone();
|
|
130
|
+
await writeBuffer.handle.mapAsync(GPUMapMode.WRITE, byteOffset, byteLength);
|
|
131
|
+
const arrayBuffer = writeBuffer.handle.getMappedRange(byteOffset, byteLength);
|
|
132
|
+
await callback(arrayBuffer, "mapped");
|
|
133
|
+
writeBuffer.handle.unmap();
|
|
134
|
+
if (mappableBuffer) {
|
|
135
|
+
this._copyBuffer(mappableBuffer, byteOffset, byteLength);
|
|
136
|
+
}
|
|
137
|
+
} finally {
|
|
138
|
+
this.device.popErrorScope((error) => {
|
|
139
|
+
this.device.reportError(new Error(`${this}.mapAndWriteAsync() ${error.message}`), this)();
|
|
140
|
+
this.device.debug();
|
|
141
|
+
});
|
|
142
|
+
mappableBuffer?.destroy();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async readAsync(byteOffset = 0, byteLength = this.byteLength - byteOffset) {
|
|
146
|
+
return this.mapAndReadAsync(
|
|
147
|
+
(arrayBuffer) => new Uint8Array(arrayBuffer.slice(0)),
|
|
148
|
+
byteOffset,
|
|
149
|
+
byteLength
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
async mapAndReadAsync(callback, byteOffset = 0, byteLength = this.byteLength - byteOffset) {
|
|
153
|
+
if (byteOffset % 8 !== 0 || byteLength % 4 !== 0) {
|
|
154
|
+
throw new Error("byteOffset must be multiple of 8 and byteLength multiple of 4");
|
|
155
|
+
}
|
|
156
|
+
if (byteOffset + byteLength > this.handle.size) {
|
|
157
|
+
throw new Error("Mapping range exceeds buffer size");
|
|
158
|
+
}
|
|
159
|
+
const isMappable = (this.usage & import_core.Buffer.MAP_READ) !== 0;
|
|
160
|
+
const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST, 0, this.byteLength) : null;
|
|
161
|
+
const readBuffer = mappableBuffer || this;
|
|
162
|
+
this.device.pushErrorScope("validation");
|
|
163
|
+
try {
|
|
164
|
+
await this.device.handle.queue.onSubmittedWorkDone();
|
|
165
|
+
if (mappableBuffer) {
|
|
166
|
+
mappableBuffer._copyBuffer(this);
|
|
167
|
+
}
|
|
168
|
+
await readBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
|
|
169
|
+
const arrayBuffer = readBuffer.handle.getMappedRange(byteOffset, byteLength);
|
|
170
|
+
const result = await callback(arrayBuffer, "mapped");
|
|
171
|
+
readBuffer.handle.unmap();
|
|
172
|
+
return result;
|
|
173
|
+
} finally {
|
|
174
|
+
this.device.popErrorScope((error) => {
|
|
175
|
+
this.device.reportError(new Error(`${this}.mapAndReadAsync() ${error.message}`), this)();
|
|
176
|
+
this.device.debug();
|
|
177
|
+
});
|
|
178
|
+
mappableBuffer?.destroy();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
readSyncWebGL(byteOffset, byteLength) {
|
|
182
|
+
throw new Error("Not implemented");
|
|
183
|
+
}
|
|
184
|
+
// INTERNAL METHODS
|
|
185
|
+
/**
|
|
186
|
+
* @todo - A small set of mappable buffers could be cached on the device,
|
|
187
|
+
* however this goes against the goal of keeping core as a thin GPU API layer.
|
|
188
|
+
*/
|
|
189
|
+
_getMappableBuffer(usage, byteOffset, byteLength) {
|
|
190
|
+
import_core.log.warn(`${this} is not readable, creating a temporary Buffer`);
|
|
191
|
+
const readableBuffer = new WebGPUBuffer(this.device, { usage, byteLength });
|
|
192
|
+
return readableBuffer;
|
|
193
|
+
}
|
|
194
|
+
_copyBuffer(sourceBuffer, byteOffset = 0, byteLength = this.byteLength) {
|
|
195
|
+
this.device.pushErrorScope("validation");
|
|
196
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
197
|
+
commandEncoder.copyBufferToBuffer(
|
|
198
|
+
sourceBuffer.handle,
|
|
199
|
+
byteOffset,
|
|
200
|
+
this.handle,
|
|
201
|
+
byteOffset,
|
|
202
|
+
byteLength
|
|
203
|
+
);
|
|
204
|
+
this.device.handle.queue.submit([commandEncoder.finish()]);
|
|
205
|
+
this.device.popErrorScope((error) => {
|
|
206
|
+
this.device.reportError(new Error(`${this}._getReadableBuffer() ${error.message}`), this)();
|
|
207
|
+
this.device.debug();
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
};
|
|
135
211
|
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// src/adapter/resources/webgpu-texture.ts
|
|
139
|
-
var import_core4 = __toESM(require_core(), 1);
|
|
212
|
+
});
|
|
140
213
|
|
|
141
214
|
// src/adapter/helpers/convert-texture-format.ts
|
|
142
215
|
function getWebGPUTextureFormat(format) {
|
|
@@ -145,346 +218,368 @@ var __exports__ = (() => {
|
|
|
145
218
|
}
|
|
146
219
|
return format;
|
|
147
220
|
}
|
|
221
|
+
var init_convert_texture_format = __esm({
|
|
222
|
+
"src/adapter/helpers/convert-texture-format.ts"() {
|
|
223
|
+
"use strict";
|
|
224
|
+
}
|
|
225
|
+
});
|
|
148
226
|
|
|
149
227
|
// src/adapter/resources/webgpu-sampler.ts
|
|
150
|
-
var import_core2
|
|
151
|
-
var
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
228
|
+
var import_core2, WebGPUSampler;
|
|
229
|
+
var init_webgpu_sampler = __esm({
|
|
230
|
+
"src/adapter/resources/webgpu-sampler.ts"() {
|
|
231
|
+
"use strict";
|
|
232
|
+
import_core2 = __toESM(require_core(), 1);
|
|
233
|
+
WebGPUSampler = class extends import_core2.Sampler {
|
|
234
|
+
device;
|
|
235
|
+
handle;
|
|
236
|
+
constructor(device, props) {
|
|
237
|
+
super(device, props);
|
|
238
|
+
this.device = device;
|
|
239
|
+
const samplerDescriptor = {
|
|
240
|
+
...this.props,
|
|
241
|
+
mipmapFilter: void 0
|
|
242
|
+
};
|
|
243
|
+
if (props.type !== "comparison-sampler") {
|
|
244
|
+
delete samplerDescriptor.compare;
|
|
245
|
+
}
|
|
246
|
+
if (props.mipmapFilter && props.mipmapFilter !== "none") {
|
|
247
|
+
samplerDescriptor.mipmapFilter = props.mipmapFilter;
|
|
248
|
+
}
|
|
249
|
+
this.handle = props.handle || this.device.handle.createSampler(samplerDescriptor);
|
|
250
|
+
this.handle.label = this.props.id;
|
|
251
|
+
}
|
|
252
|
+
destroy() {
|
|
253
|
+
this.handle = null;
|
|
254
|
+
}
|
|
160
255
|
};
|
|
161
|
-
if (props.type !== "comparison-sampler") {
|
|
162
|
-
delete samplerDescriptor.compare;
|
|
163
|
-
}
|
|
164
|
-
if (props.mipmapFilter && props.mipmapFilter !== "none") {
|
|
165
|
-
samplerDescriptor.mipmapFilter = props.mipmapFilter;
|
|
166
|
-
}
|
|
167
|
-
this.handle = this.handle || this.device.handle.createSampler(samplerDescriptor);
|
|
168
|
-
this.handle.label = this.props.id;
|
|
169
256
|
}
|
|
170
|
-
|
|
171
|
-
this.handle = null;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
257
|
+
});
|
|
174
258
|
|
|
175
259
|
// src/adapter/resources/webgpu-texture-view.ts
|
|
176
|
-
var import_core3
|
|
177
|
-
var
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
260
|
+
var import_core3, WebGPUTextureView;
|
|
261
|
+
var init_webgpu_texture_view = __esm({
|
|
262
|
+
"src/adapter/resources/webgpu-texture-view.ts"() {
|
|
263
|
+
"use strict";
|
|
264
|
+
import_core3 = __toESM(require_core(), 1);
|
|
265
|
+
WebGPUTextureView = class extends import_core3.TextureView {
|
|
266
|
+
device;
|
|
267
|
+
handle;
|
|
268
|
+
texture;
|
|
269
|
+
constructor(device, props) {
|
|
270
|
+
super(device, props);
|
|
271
|
+
this.device = device;
|
|
272
|
+
this.texture = props.texture;
|
|
273
|
+
this.device.pushErrorScope("validation");
|
|
274
|
+
this.handle = // props.handle ||
|
|
275
|
+
this.texture.handle.createView({
|
|
276
|
+
format: this.props.format || this.texture.format,
|
|
277
|
+
dimension: this.props.dimension || this.texture.dimension,
|
|
278
|
+
aspect: this.props.aspect,
|
|
279
|
+
baseMipLevel: this.props.baseMipLevel,
|
|
280
|
+
mipLevelCount: this.props.mipLevelCount,
|
|
281
|
+
baseArrayLayer: this.props.baseArrayLayer,
|
|
282
|
+
arrayLayerCount: this.props.arrayLayerCount
|
|
283
|
+
});
|
|
284
|
+
this.device.popErrorScope((error) => {
|
|
285
|
+
this.device.reportError(new Error(`TextureView constructor: ${error.message}`), this)();
|
|
286
|
+
this.device.debug();
|
|
287
|
+
});
|
|
288
|
+
this.handle.label = this.props.id;
|
|
289
|
+
}
|
|
290
|
+
destroy() {
|
|
291
|
+
this.handle = null;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
201
294
|
}
|
|
202
|
-
};
|
|
295
|
+
});
|
|
203
296
|
|
|
204
297
|
// src/adapter/resources/webgpu-texture.ts
|
|
205
|
-
var
|
|
206
|
-
|
|
207
|
-
"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
this.
|
|
240
|
-
|
|
241
|
-
|
|
298
|
+
var import_core4, WebGPUTexture;
|
|
299
|
+
var init_webgpu_texture = __esm({
|
|
300
|
+
"src/adapter/resources/webgpu-texture.ts"() {
|
|
301
|
+
"use strict";
|
|
302
|
+
import_core4 = __toESM(require_core(), 1);
|
|
303
|
+
init_convert_texture_format();
|
|
304
|
+
init_webgpu_sampler();
|
|
305
|
+
init_webgpu_texture_view();
|
|
306
|
+
WebGPUTexture = class extends import_core4.Texture {
|
|
307
|
+
device;
|
|
308
|
+
handle;
|
|
309
|
+
sampler;
|
|
310
|
+
view;
|
|
311
|
+
constructor(device, props) {
|
|
312
|
+
super(device, props);
|
|
313
|
+
this.device = device;
|
|
314
|
+
if (this.dimension === "cube") {
|
|
315
|
+
this.depth = 6;
|
|
316
|
+
}
|
|
317
|
+
this.device.pushErrorScope("out-of-memory");
|
|
318
|
+
this.device.pushErrorScope("validation");
|
|
319
|
+
this.handle = this.props.handle || this.device.handle.createTexture({
|
|
320
|
+
label: this.id,
|
|
321
|
+
size: {
|
|
322
|
+
width: this.width,
|
|
323
|
+
height: this.height,
|
|
324
|
+
depthOrArrayLayers: this.depth
|
|
325
|
+
},
|
|
326
|
+
usage: this.props.usage || import_core4.Texture.TEXTURE | import_core4.Texture.COPY_DST,
|
|
327
|
+
dimension: this.baseDimension,
|
|
328
|
+
format: getWebGPUTextureFormat(this.format),
|
|
329
|
+
mipLevelCount: this.mipLevels,
|
|
330
|
+
sampleCount: this.props.samples
|
|
331
|
+
});
|
|
332
|
+
this.device.popErrorScope((error) => {
|
|
333
|
+
this.device.reportError(new Error(`${this} constructor: ${error.message}`), this)();
|
|
334
|
+
this.device.debug();
|
|
335
|
+
});
|
|
336
|
+
this.device.popErrorScope((error) => {
|
|
337
|
+
this.device.reportError(new Error(`${this} out of memory: ${error.message}`), this)();
|
|
338
|
+
this.device.debug();
|
|
339
|
+
});
|
|
340
|
+
if (this.props.handle) {
|
|
341
|
+
this.handle.label ||= this.id;
|
|
342
|
+
this.width = this.handle.width;
|
|
343
|
+
this.height = this.handle.height;
|
|
344
|
+
}
|
|
345
|
+
this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler || {});
|
|
346
|
+
this.view = new WebGPUTextureView(this.device, {
|
|
347
|
+
...this.props,
|
|
348
|
+
texture: this,
|
|
349
|
+
mipLevelCount: this.mipLevels,
|
|
350
|
+
// Note: arrayLayerCount controls the view of array textures, but does not apply to 3d texture depths
|
|
351
|
+
arrayLayerCount: this.dimension !== "3d" ? this.depth : 1
|
|
352
|
+
});
|
|
353
|
+
this._initializeData(props.data);
|
|
242
354
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
encoder.copyTextureToBuffer(
|
|
355
|
-
{ texture },
|
|
356
|
-
{ buffer, rowPitch: textureWidth * 4 },
|
|
357
|
-
[textureWidth, textureHeight],
|
|
358
|
-
);
|
|
359
|
-
device.submit([encoder.finish()]);
|
|
360
|
-
|
|
361
|
-
// Get the data on the CPU.
|
|
362
|
-
await buffer.mapAsync(GPUMapMode.READ);
|
|
363
|
-
saveScreenshot(buffer.getMappedRange());
|
|
364
|
-
buffer.unmap();
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
setImageData(imageData, usage): this {
|
|
368
|
-
let data = null;
|
|
369
|
-
|
|
370
|
-
const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
|
|
371
|
-
if (bytesPerRow == img.width * 4) {
|
|
372
|
-
data = imageData.data;
|
|
373
|
-
} else {
|
|
374
|
-
data = new Uint8Array(bytesPerRow * img.height);
|
|
375
|
-
let imagePixelIndex = 0;
|
|
376
|
-
for (let y = 0; y < img.height; ++y) {
|
|
377
|
-
for (let x = 0; x < img.width; ++x) {
|
|
378
|
-
const i = x * 4 + y * bytesPerRow;
|
|
379
|
-
data[i] = imageData.data[imagePixelIndex];
|
|
380
|
-
data[i + 1] = imageData.data[imagePixelIndex + 1];
|
|
381
|
-
data[i + 2] = imageData.data[imagePixelIndex + 2];
|
|
382
|
-
data[i + 3] = imageData.data[imagePixelIndex + 3];
|
|
383
|
-
imagePixelIndex += 4;
|
|
355
|
+
destroy() {
|
|
356
|
+
this.handle?.destroy();
|
|
357
|
+
this.handle = null;
|
|
358
|
+
}
|
|
359
|
+
createView(props) {
|
|
360
|
+
return new WebGPUTextureView(this.device, { ...props, texture: this });
|
|
361
|
+
}
|
|
362
|
+
copyImageData(options_) {
|
|
363
|
+
const { width, height, depth } = this;
|
|
364
|
+
const options = this._normalizeCopyImageDataOptions(options_);
|
|
365
|
+
this.device.pushErrorScope("validation");
|
|
366
|
+
this.device.handle.queue.writeTexture(
|
|
367
|
+
// destination: GPUImageCopyTexture
|
|
368
|
+
{
|
|
369
|
+
// texture subresource
|
|
370
|
+
texture: this.handle,
|
|
371
|
+
mipLevel: options.mipLevel,
|
|
372
|
+
aspect: options.aspect,
|
|
373
|
+
// origin to write to
|
|
374
|
+
origin: [options.x, options.y, options.z]
|
|
375
|
+
},
|
|
376
|
+
// data
|
|
377
|
+
options.data,
|
|
378
|
+
// dataLayout: GPUImageDataLayout
|
|
379
|
+
{
|
|
380
|
+
offset: options.byteOffset,
|
|
381
|
+
bytesPerRow: options.bytesPerRow,
|
|
382
|
+
rowsPerImage: options.rowsPerImage
|
|
383
|
+
},
|
|
384
|
+
// size: GPUExtent3D - extents of the content to write
|
|
385
|
+
[width, height, depth]
|
|
386
|
+
);
|
|
387
|
+
this.device.popErrorScope((error) => {
|
|
388
|
+
this.device.reportError(new Error(`copyImageData: ${error.message}`), this)();
|
|
389
|
+
this.device.debug();
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
copyExternalImage(options_) {
|
|
393
|
+
const options = this._normalizeCopyExternalImageOptions(options_);
|
|
394
|
+
this.device.pushErrorScope("validation");
|
|
395
|
+
this.device.handle.queue.copyExternalImageToTexture(
|
|
396
|
+
// source: GPUImageCopyExternalImage
|
|
397
|
+
{
|
|
398
|
+
source: options.image,
|
|
399
|
+
origin: [options.sourceX, options.sourceY],
|
|
400
|
+
flipY: options.flipY
|
|
401
|
+
},
|
|
402
|
+
// destination: GPUImageCopyTextureTagged
|
|
403
|
+
{
|
|
404
|
+
texture: this.handle,
|
|
405
|
+
origin: [options.x, options.y, 0],
|
|
406
|
+
// options.depth],
|
|
407
|
+
mipLevel: options.mipLevel,
|
|
408
|
+
aspect: options.aspect,
|
|
409
|
+
colorSpace: options.colorSpace,
|
|
410
|
+
premultipliedAlpha: options.premultipliedAlpha
|
|
411
|
+
},
|
|
412
|
+
// copySize: GPUExtent3D
|
|
413
|
+
[options.width, options.height, 1]
|
|
414
|
+
);
|
|
415
|
+
this.device.popErrorScope((error) => {
|
|
416
|
+
this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
|
|
417
|
+
this.device.debug();
|
|
418
|
+
});
|
|
419
|
+
return { width: options.width, height: options.height };
|
|
420
|
+
}
|
|
421
|
+
generateMipmapsWebGL() {
|
|
422
|
+
import_core4.log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
|
|
423
|
+
}
|
|
424
|
+
// WebGPU specific
|
|
425
|
+
/*
|
|
426
|
+
async readPixels() {
|
|
427
|
+
const readbackBuffer = device.createBuffer({
|
|
428
|
+
usage: Buffer.COPY_DST | Buffer.MAP_READ,
|
|
429
|
+
size: 4 * textureWidth * textureHeight,
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Copy data from the texture to the buffer.
|
|
433
|
+
const encoder = device.createCommandEncoder();
|
|
434
|
+
encoder.copyTextureToBuffer(
|
|
435
|
+
{ texture },
|
|
436
|
+
{ buffer, rowPitch: textureWidth * 4 },
|
|
437
|
+
[textureWidth, textureHeight],
|
|
438
|
+
);
|
|
439
|
+
device.submit([encoder.finish()]);
|
|
440
|
+
|
|
441
|
+
// Get the data on the CPU.
|
|
442
|
+
await buffer.mapAndReadAsync(GPUMapMode.READ);
|
|
443
|
+
saveScreenshot(buffer.getMappedRange());
|
|
444
|
+
buffer.unmap();
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
setImageData(imageData, usage): this {
|
|
448
|
+
let data = null;
|
|
449
|
+
|
|
450
|
+
const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
|
|
451
|
+
if (bytesPerRow == img.width * 4) {
|
|
452
|
+
data = imageData.data;
|
|
453
|
+
} else {
|
|
454
|
+
data = new Uint8Array(bytesPerRow * img.height);
|
|
455
|
+
let imagePixelIndex = 0;
|
|
456
|
+
for (let y = 0; y < img.height; ++y) {
|
|
457
|
+
for (let x = 0; x < img.width; ++x) {
|
|
458
|
+
const i = x * 4 + y * bytesPerRow;
|
|
459
|
+
data[i] = imageData.data[imagePixelIndex];
|
|
460
|
+
data[i + 1] = imageData.data[imagePixelIndex + 1];
|
|
461
|
+
data[i + 2] = imageData.data[imagePixelIndex + 2];
|
|
462
|
+
data[i + 3] = imageData.data[imagePixelIndex + 3];
|
|
463
|
+
imagePixelIndex += 4;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
384
466
|
}
|
|
467
|
+
return this;
|
|
385
468
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
469
|
+
|
|
470
|
+
setBuffer(textureDataBuffer, {bytesPerRow}): this {
|
|
471
|
+
const commandEncoder = this.device.handle.createCommandEncoder();
|
|
472
|
+
commandEncoder.copyBufferToTexture(
|
|
473
|
+
{
|
|
474
|
+
buffer: textureDataBuffer,
|
|
475
|
+
bytesPerRow
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
texture: this.handle
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
width,
|
|
482
|
+
height,
|
|
483
|
+
depth
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
|
|
488
|
+
return this;
|
|
404
489
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
*/
|
|
411
|
-
};
|
|
490
|
+
*/
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
});
|
|
412
494
|
|
|
413
495
|
// src/adapter/resources/webgpu-external-texture.ts
|
|
414
|
-
var import_core5
|
|
415
|
-
var
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
496
|
+
var import_core5, WebGPUExternalTexture;
|
|
497
|
+
var init_webgpu_external_texture = __esm({
|
|
498
|
+
"src/adapter/resources/webgpu-external-texture.ts"() {
|
|
499
|
+
"use strict";
|
|
500
|
+
import_core5 = __toESM(require_core(), 1);
|
|
501
|
+
init_webgpu_sampler();
|
|
502
|
+
WebGPUExternalTexture = class extends import_core5.ExternalTexture {
|
|
503
|
+
device;
|
|
504
|
+
handle;
|
|
505
|
+
sampler;
|
|
506
|
+
constructor(device, props) {
|
|
507
|
+
super(device, props);
|
|
508
|
+
this.device = device;
|
|
509
|
+
this.handle = this.props.handle || this.device.handle.importExternalTexture({
|
|
510
|
+
source: props.source,
|
|
511
|
+
colorSpace: props.colorSpace
|
|
512
|
+
});
|
|
513
|
+
this.sampler = null;
|
|
514
|
+
}
|
|
515
|
+
destroy() {
|
|
516
|
+
this.handle = null;
|
|
517
|
+
}
|
|
518
|
+
/** Set default sampler */
|
|
519
|
+
setSampler(sampler) {
|
|
520
|
+
this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
435
524
|
}
|
|
436
|
-
};
|
|
525
|
+
});
|
|
437
526
|
|
|
438
527
|
// src/adapter/resources/webgpu-shader.ts
|
|
439
|
-
var import_core6
|
|
440
|
-
var
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
528
|
+
var import_core6, WebGPUShader;
|
|
529
|
+
var init_webgpu_shader = __esm({
|
|
530
|
+
"src/adapter/resources/webgpu-shader.ts"() {
|
|
531
|
+
"use strict";
|
|
532
|
+
import_core6 = __toESM(require_core(), 1);
|
|
533
|
+
WebGPUShader = class extends import_core6.Shader {
|
|
534
|
+
device;
|
|
535
|
+
handle;
|
|
536
|
+
constructor(device, props) {
|
|
537
|
+
super(device, props);
|
|
538
|
+
this.device = device;
|
|
539
|
+
const isGLSL = props.source.includes("#version");
|
|
540
|
+
if (this.props.language === "glsl" || isGLSL) {
|
|
541
|
+
throw new Error("GLSL shaders are not supported in WebGPU");
|
|
542
|
+
}
|
|
543
|
+
this.device.pushErrorScope("validation");
|
|
544
|
+
this.handle = this.props.handle || this.device.handle.createShaderModule({ code: props.source });
|
|
545
|
+
this.device.popErrorScope((error) => {
|
|
546
|
+
this.device.reportError(
|
|
547
|
+
new Error(`${this} creation failed:
|
|
548
|
+
"${error.message}"`),
|
|
549
|
+
this,
|
|
550
|
+
this.props.source
|
|
551
|
+
)();
|
|
552
|
+
this.device.debug();
|
|
553
|
+
});
|
|
554
|
+
this.handle.label = this.props.id;
|
|
555
|
+
this._checkCompilationError();
|
|
456
556
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return compilationInfo.messages;
|
|
557
|
+
get asyncCompilationStatus() {
|
|
558
|
+
return this.getCompilationInfo().then(() => this.compilationStatus);
|
|
559
|
+
}
|
|
560
|
+
async _checkCompilationError() {
|
|
561
|
+
const shaderLog = await this.getCompilationInfo();
|
|
562
|
+
const hasErrors = Boolean(shaderLog.find((msg) => msg.type === "error"));
|
|
563
|
+
this.compilationStatus = hasErrors ? "error" : "success";
|
|
564
|
+
this.debugShader();
|
|
565
|
+
if (this.compilationStatus === "error") {
|
|
566
|
+
this.device.reportError(new Error(`Shader compilation error`), this, shaderLog)();
|
|
567
|
+
this.device.debug();
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
destroy() {
|
|
571
|
+
this.handle = null;
|
|
572
|
+
}
|
|
573
|
+
/** Returns compilation info for this shader */
|
|
574
|
+
async getCompilationInfo() {
|
|
575
|
+
const compilationInfo = await this.handle.getCompilationInfo();
|
|
576
|
+
return compilationInfo.messages;
|
|
577
|
+
}
|
|
578
|
+
};
|
|
480
579
|
}
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
484
|
-
var import_core10 = __toESM(require_core(), 1);
|
|
580
|
+
});
|
|
485
581
|
|
|
486
582
|
// src/adapter/helpers/webgpu-parameters.ts
|
|
487
|
-
var import_core7 = __toESM(require_core(), 1);
|
|
488
583
|
function addDepthStencil(descriptor) {
|
|
489
584
|
descriptor.depthStencil = descriptor.depthStencil || {
|
|
490
585
|
// required, set something
|
|
@@ -505,157 +600,9 @@ var __exports__ = (() => {
|
|
|
505
600
|
const depthStencil = addDepthStencil(descriptor);
|
|
506
601
|
return depthStencil.stencilBack;
|
|
507
602
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
descriptor.primitive = descriptor.primitive || {};
|
|
512
|
-
descriptor.primitive.cullMode = value;
|
|
513
|
-
},
|
|
514
|
-
frontFace: (parameter, value, descriptor) => {
|
|
515
|
-
descriptor.primitive = descriptor.primitive || {};
|
|
516
|
-
descriptor.primitive.frontFace = value;
|
|
517
|
-
},
|
|
518
|
-
// DEPTH
|
|
519
|
-
depthWriteEnabled: (parameter, value, descriptor) => {
|
|
520
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
521
|
-
depthStencil.depthWriteEnabled = value;
|
|
522
|
-
},
|
|
523
|
-
depthCompare: (parameter, value, descriptor) => {
|
|
524
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
525
|
-
depthStencil.depthCompare = value;
|
|
526
|
-
},
|
|
527
|
-
depthFormat: (parameter, value, descriptor) => {
|
|
528
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
529
|
-
depthStencil.format = value;
|
|
530
|
-
},
|
|
531
|
-
depthBias: (parameter, value, descriptor) => {
|
|
532
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
533
|
-
depthStencil.depthBias = value;
|
|
534
|
-
},
|
|
535
|
-
depthBiasSlopeScale: (parameter, value, descriptor) => {
|
|
536
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
537
|
-
depthStencil.depthBiasSlopeScale = value;
|
|
538
|
-
},
|
|
539
|
-
depthBiasClamp: (parameter, value, descriptor) => {
|
|
540
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
541
|
-
depthStencil.depthBiasClamp = value;
|
|
542
|
-
},
|
|
543
|
-
// STENCIL
|
|
544
|
-
stencilReadMask: (parameter, value, descriptor) => {
|
|
545
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
546
|
-
depthStencil.stencilReadMask = value;
|
|
547
|
-
},
|
|
548
|
-
stencilWriteMask: (parameter, value, descriptor) => {
|
|
549
|
-
const depthStencil = addDepthStencil(descriptor);
|
|
550
|
-
depthStencil.stencilWriteMask = value;
|
|
551
|
-
},
|
|
552
|
-
stencilCompare: (parameter, value, descriptor) => {
|
|
553
|
-
const stencilFront = addDepthStencilFront(descriptor);
|
|
554
|
-
const stencilBack = addDepthStencilBack(descriptor);
|
|
555
|
-
stencilFront.compare = value;
|
|
556
|
-
stencilBack.compare = value;
|
|
557
|
-
},
|
|
558
|
-
stencilPassOperation: (parameter, value, descriptor) => {
|
|
559
|
-
const stencilFront = addDepthStencilFront(descriptor);
|
|
560
|
-
const stencilBack = addDepthStencilBack(descriptor);
|
|
561
|
-
stencilFront.passOp = value;
|
|
562
|
-
stencilBack.passOp = value;
|
|
563
|
-
},
|
|
564
|
-
stencilFailOperation: (parameter, value, descriptor) => {
|
|
565
|
-
const stencilFront = addDepthStencilFront(descriptor);
|
|
566
|
-
const stencilBack = addDepthStencilBack(descriptor);
|
|
567
|
-
stencilFront.failOp = value;
|
|
568
|
-
stencilBack.failOp = value;
|
|
569
|
-
},
|
|
570
|
-
stencilDepthFailOperation: (parameter, value, descriptor) => {
|
|
571
|
-
const stencilFront = addDepthStencilFront(descriptor);
|
|
572
|
-
const stencilBack = addDepthStencilBack(descriptor);
|
|
573
|
-
stencilFront.depthFailOp = value;
|
|
574
|
-
stencilBack.depthFailOp = value;
|
|
575
|
-
},
|
|
576
|
-
// MULTISAMPLE
|
|
577
|
-
sampleCount: (parameter, value, descriptor) => {
|
|
578
|
-
descriptor.multisample = descriptor.multisample || {};
|
|
579
|
-
descriptor.multisample.count = value;
|
|
580
|
-
},
|
|
581
|
-
sampleMask: (parameter, value, descriptor) => {
|
|
582
|
-
descriptor.multisample = descriptor.multisample || {};
|
|
583
|
-
descriptor.multisample.mask = value;
|
|
584
|
-
},
|
|
585
|
-
sampleAlphaToCoverageEnabled: (parameter, value, descriptor) => {
|
|
586
|
-
descriptor.multisample = descriptor.multisample || {};
|
|
587
|
-
descriptor.multisample.alphaToCoverageEnabled = value;
|
|
588
|
-
},
|
|
589
|
-
// COLOR
|
|
590
|
-
colorMask: (parameter, value, descriptor) => {
|
|
591
|
-
const targets = addColorState(descriptor);
|
|
592
|
-
targets[0].writeMask = value;
|
|
593
|
-
},
|
|
594
|
-
blendColorOperation: (parameter, value, descriptor) => {
|
|
595
|
-
addColorState(descriptor);
|
|
596
|
-
}
|
|
597
|
-
/*
|
|
598
|
-
blendColorSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
599
|
-
addColorState(descriptor);
|
|
600
|
-
targets[0].blend = targets[0].blend || {};
|
|
601
|
-
targets[0].blend.color = targets[0].blend.color || {};
|
|
602
|
-
targets[0].blend.color.srcTarget = value;
|
|
603
|
-
},
|
|
604
|
-
|
|
605
|
-
blendColorDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
606
|
-
addColorState(descriptor);
|
|
607
|
-
targets[0].blend = targets[0].blend || {};
|
|
608
|
-
targets[0].blend.color = targets[0].blend.color || {};
|
|
609
|
-
targets[0].blend.color.dstTarget = value;
|
|
610
|
-
},
|
|
611
|
-
|
|
612
|
-
blendAlphaOperation: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
613
|
-
addColorState(descriptor);
|
|
614
|
-
targets[0].blend = targets[0].blend || {};
|
|
615
|
-
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
616
|
-
targets[0].blend.alpha.operation = value;
|
|
617
|
-
},
|
|
618
|
-
|
|
619
|
-
blendAlphaSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
620
|
-
addColorState(descriptor);
|
|
621
|
-
targets[0].blend = targets[0].blend || {};
|
|
622
|
-
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
623
|
-
targets[0].blend.alpha.srcTarget = value;
|
|
624
|
-
},
|
|
625
|
-
|
|
626
|
-
blendAlphaDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
|
|
627
|
-
addColorState(descriptor);
|
|
628
|
-
targets[0].blend = targets[0].blend || {};
|
|
629
|
-
targets[0].blend.alpha = targets[0].blend.alpha || {};
|
|
630
|
-
targets[0].blend.alpha.dstTarget = value;
|
|
631
|
-
},
|
|
632
|
-
*/
|
|
633
|
-
};
|
|
634
|
-
var DEFAULT_PIPELINE_DESCRIPTOR = {
|
|
635
|
-
// depthStencil: {
|
|
636
|
-
// stencilFront: {},
|
|
637
|
-
// stencilBack: {},
|
|
638
|
-
// // depthWriteEnabled: true,
|
|
639
|
-
// // depthCompare: 'less',
|
|
640
|
-
// // format: 'depth24plus-stencil8',
|
|
641
|
-
// },
|
|
642
|
-
primitive: {
|
|
643
|
-
cullMode: "back",
|
|
644
|
-
topology: "triangle-list"
|
|
645
|
-
},
|
|
646
|
-
vertex: {
|
|
647
|
-
module: void 0,
|
|
648
|
-
entryPoint: "main"
|
|
649
|
-
},
|
|
650
|
-
fragment: {
|
|
651
|
-
module: void 0,
|
|
652
|
-
entryPoint: "main",
|
|
653
|
-
targets: [
|
|
654
|
-
// { format: props.color0Format || 'bgra8unorm' }
|
|
655
|
-
]
|
|
656
|
-
},
|
|
657
|
-
layout: "auto"
|
|
658
|
-
};
|
|
603
|
+
function notSupported(key, value, descriptor) {
|
|
604
|
+
import_core7.log.warn(`${key} parameter not supported in WebGPU`)();
|
|
605
|
+
}
|
|
659
606
|
function applyParametersToRenderPipelineDescriptor(pipelineDescriptor, parameters = {}) {
|
|
660
607
|
Object.assign(pipelineDescriptor, { ...DEFAULT_PIPELINE_DESCRIPTOR, ...pipelineDescriptor });
|
|
661
608
|
setParameters(pipelineDescriptor, parameters);
|
|
@@ -663,14 +610,14 @@ var __exports__ = (() => {
|
|
|
663
610
|
function setParameters(pipelineDescriptor, parameters) {
|
|
664
611
|
for (const [key, value] of Object.entries(parameters)) {
|
|
665
612
|
const setterFunction = PARAMETER_TABLE[key];
|
|
666
|
-
if (
|
|
667
|
-
|
|
668
|
-
|
|
613
|
+
if (setterFunction) {
|
|
614
|
+
setterFunction(key, value, pipelineDescriptor);
|
|
615
|
+
} else {
|
|
616
|
+
import_core7.log.error(`Illegal parameter ${key} in WebGPU`)();
|
|
669
617
|
}
|
|
670
|
-
setterFunction(key, value, pipelineDescriptor);
|
|
671
618
|
}
|
|
672
619
|
}
|
|
673
|
-
function addColorState(descriptor) {
|
|
620
|
+
function addColorState(descriptor, attachment) {
|
|
674
621
|
descriptor.fragment.targets = descriptor.fragment?.targets || [];
|
|
675
622
|
if (!Array.isArray(descriptor.fragment?.targets)) {
|
|
676
623
|
import_core7.log.warn("parameters: no targets array")();
|
|
@@ -678,23 +625,201 @@ var __exports__ = (() => {
|
|
|
678
625
|
if (descriptor.fragment?.targets?.length === 0) {
|
|
679
626
|
descriptor.fragment.targets?.push({});
|
|
680
627
|
}
|
|
681
|
-
return descriptor.fragment?.targets;
|
|
628
|
+
return descriptor.fragment?.targets?.[0];
|
|
629
|
+
}
|
|
630
|
+
function addBlendState(descriptor, attachment) {
|
|
631
|
+
const target = addColorState(descriptor, attachment);
|
|
632
|
+
target.blend = target.blend || { color: {}, alpha: {} };
|
|
633
|
+
return target.blend;
|
|
682
634
|
}
|
|
635
|
+
var import_core7, PARAMETER_TABLE, DEFAULT_PIPELINE_DESCRIPTOR;
|
|
636
|
+
var init_webgpu_parameters = __esm({
|
|
637
|
+
"src/adapter/helpers/webgpu-parameters.ts"() {
|
|
638
|
+
"use strict";
|
|
639
|
+
import_core7 = __toESM(require_core(), 1);
|
|
640
|
+
PARAMETER_TABLE = {
|
|
641
|
+
// RASTERIZATION PARAMETERS
|
|
642
|
+
cullMode: (_, value, descriptor) => {
|
|
643
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
644
|
+
descriptor.primitive.cullMode = value;
|
|
645
|
+
},
|
|
646
|
+
frontFace: (_, value, descriptor) => {
|
|
647
|
+
descriptor.primitive = descriptor.primitive || {};
|
|
648
|
+
descriptor.primitive.frontFace = value;
|
|
649
|
+
},
|
|
650
|
+
// DEPTH
|
|
651
|
+
depthWriteEnabled: (_, value, descriptor) => {
|
|
652
|
+
if (value) {
|
|
653
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
654
|
+
depthStencil.depthWriteEnabled = value;
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
depthCompare: (_, value, descriptor) => {
|
|
658
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
659
|
+
depthStencil.depthCompare = value;
|
|
660
|
+
},
|
|
661
|
+
depthFormat: (_, value, descriptor) => {
|
|
662
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
663
|
+
depthStencil.format = value;
|
|
664
|
+
},
|
|
665
|
+
depthBias: (_, value, descriptor) => {
|
|
666
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
667
|
+
depthStencil.depthBias = value;
|
|
668
|
+
},
|
|
669
|
+
depthBiasSlopeScale: (_, value, descriptor) => {
|
|
670
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
671
|
+
depthStencil.depthBiasSlopeScale = value;
|
|
672
|
+
},
|
|
673
|
+
depthBiasClamp: (_, value, descriptor) => {
|
|
674
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
675
|
+
depthStencil.depthBiasClamp = value;
|
|
676
|
+
},
|
|
677
|
+
// STENCIL
|
|
678
|
+
stencilReadMask: (_, value, descriptor) => {
|
|
679
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
680
|
+
depthStencil.stencilReadMask = value;
|
|
681
|
+
},
|
|
682
|
+
stencilWriteMask: (_, value, descriptor) => {
|
|
683
|
+
const depthStencil = addDepthStencil(descriptor);
|
|
684
|
+
depthStencil.stencilWriteMask = value;
|
|
685
|
+
},
|
|
686
|
+
stencilCompare: (_, value, descriptor) => {
|
|
687
|
+
const stencilFront = addDepthStencilFront(descriptor);
|
|
688
|
+
const stencilBack = addDepthStencilBack(descriptor);
|
|
689
|
+
stencilFront.compare = value;
|
|
690
|
+
stencilBack.compare = value;
|
|
691
|
+
},
|
|
692
|
+
stencilPassOperation: (_, value, descriptor) => {
|
|
693
|
+
const stencilFront = addDepthStencilFront(descriptor);
|
|
694
|
+
const stencilBack = addDepthStencilBack(descriptor);
|
|
695
|
+
stencilFront.passOp = value;
|
|
696
|
+
stencilBack.passOp = value;
|
|
697
|
+
},
|
|
698
|
+
stencilFailOperation: (_, value, descriptor) => {
|
|
699
|
+
const stencilFront = addDepthStencilFront(descriptor);
|
|
700
|
+
const stencilBack = addDepthStencilBack(descriptor);
|
|
701
|
+
stencilFront.failOp = value;
|
|
702
|
+
stencilBack.failOp = value;
|
|
703
|
+
},
|
|
704
|
+
stencilDepthFailOperation: (_, value, descriptor) => {
|
|
705
|
+
const stencilFront = addDepthStencilFront(descriptor);
|
|
706
|
+
const stencilBack = addDepthStencilBack(descriptor);
|
|
707
|
+
stencilFront.depthFailOp = value;
|
|
708
|
+
stencilBack.depthFailOp = value;
|
|
709
|
+
},
|
|
710
|
+
// MULTISAMPLE
|
|
711
|
+
sampleCount: (_, value, descriptor) => {
|
|
712
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
713
|
+
descriptor.multisample.count = value;
|
|
714
|
+
},
|
|
715
|
+
sampleMask: (_, value, descriptor) => {
|
|
716
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
717
|
+
descriptor.multisample.mask = value;
|
|
718
|
+
},
|
|
719
|
+
sampleAlphaToCoverageEnabled: (_, value, descriptor) => {
|
|
720
|
+
descriptor.multisample = descriptor.multisample || {};
|
|
721
|
+
descriptor.multisample.alphaToCoverageEnabled = value;
|
|
722
|
+
},
|
|
723
|
+
// COLOR
|
|
724
|
+
colorMask: (_, value, descriptor) => {
|
|
725
|
+
const target = addColorState(descriptor, 0);
|
|
726
|
+
target.writeMask = value;
|
|
727
|
+
},
|
|
728
|
+
blend: (_, value, descriptor) => {
|
|
729
|
+
if (value) {
|
|
730
|
+
addBlendState(descriptor, 0);
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
blendColorOperation: (_, value, descriptor) => {
|
|
734
|
+
const blend = addBlendState(descriptor, 0);
|
|
735
|
+
blend.color = blend.color || {};
|
|
736
|
+
blend.color.operation = value;
|
|
737
|
+
},
|
|
738
|
+
blendColorSrcFactor: (_, value, descriptor) => {
|
|
739
|
+
const blend = addBlendState(descriptor, 0);
|
|
740
|
+
blend.color = blend.color || {};
|
|
741
|
+
blend.color.srcFactor = value;
|
|
742
|
+
},
|
|
743
|
+
blendColorDstFactor: (_, value, descriptor) => {
|
|
744
|
+
const blend = addBlendState(descriptor, 0);
|
|
745
|
+
blend.color.dstFactor = value;
|
|
746
|
+
},
|
|
747
|
+
blendAlphaOperation: (_, value, descriptor) => {
|
|
748
|
+
const blend = addBlendState(descriptor, 0);
|
|
749
|
+
blend.alpha = blend.alpha || {};
|
|
750
|
+
blend.alpha.operation = value;
|
|
751
|
+
},
|
|
752
|
+
blendAlphaSrcFactor: (_, value, descriptor) => {
|
|
753
|
+
const blend = addBlendState(descriptor, 0);
|
|
754
|
+
blend.alpha = blend.alpha || {};
|
|
755
|
+
blend.alpha.srcFactor = value;
|
|
756
|
+
},
|
|
757
|
+
blendAlphaDstFactor: (_, value, descriptor) => {
|
|
758
|
+
const blend = addBlendState(descriptor, 0);
|
|
759
|
+
blend.alpha = blend.alpha || {};
|
|
760
|
+
blend.alpha.dstFactor = value;
|
|
761
|
+
},
|
|
762
|
+
unclippedDepth: notSupported,
|
|
763
|
+
provokingVertex: notSupported,
|
|
764
|
+
polygonMode: notSupported,
|
|
765
|
+
polygonOffsetLine: notSupported,
|
|
766
|
+
clipDistance0: notSupported,
|
|
767
|
+
clipDistance1: notSupported,
|
|
768
|
+
clipDistance2: notSupported,
|
|
769
|
+
clipDistance3: notSupported,
|
|
770
|
+
clipDistance4: notSupported,
|
|
771
|
+
clipDistance5: notSupported,
|
|
772
|
+
clipDistance6: notSupported,
|
|
773
|
+
clipDistance7: notSupported
|
|
774
|
+
};
|
|
775
|
+
DEFAULT_PIPELINE_DESCRIPTOR = {
|
|
776
|
+
// depthStencil: {
|
|
777
|
+
// stencilFront: {},
|
|
778
|
+
// stencilBack: {},
|
|
779
|
+
// // depthWriteEnabled: true,
|
|
780
|
+
// // depthCompare: 'less',
|
|
781
|
+
// // format: 'depth24plus-stencil8',
|
|
782
|
+
// },
|
|
783
|
+
primitive: {
|
|
784
|
+
cullMode: "back",
|
|
785
|
+
topology: "triangle-list"
|
|
786
|
+
},
|
|
787
|
+
vertex: {
|
|
788
|
+
module: void 0,
|
|
789
|
+
entryPoint: "main"
|
|
790
|
+
},
|
|
791
|
+
fragment: {
|
|
792
|
+
module: void 0,
|
|
793
|
+
entryPoint: "main",
|
|
794
|
+
targets: [
|
|
795
|
+
// { format: props.color0Format || 'bgra8unorm' }
|
|
796
|
+
]
|
|
797
|
+
},
|
|
798
|
+
layout: "auto"
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
});
|
|
683
802
|
|
|
684
803
|
// src/adapter/helpers/get-bind-group.ts
|
|
685
|
-
var import_core8 = __toESM(require_core(), 1);
|
|
686
804
|
function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
|
|
687
805
|
const entries = getBindGroupEntries(bindings, shaderLayout);
|
|
688
|
-
|
|
806
|
+
device.pushErrorScope("validation");
|
|
807
|
+
const bindGroup = device.createBindGroup({
|
|
689
808
|
layout: bindGroupLayout,
|
|
690
809
|
entries
|
|
691
810
|
});
|
|
811
|
+
device.popErrorScope().then((error) => {
|
|
812
|
+
if (error) {
|
|
813
|
+
import_core8.log.error(`bindGroup creation: ${error.message}`, bindGroup)();
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
return bindGroup;
|
|
692
817
|
}
|
|
693
|
-
function getShaderLayoutBinding(shaderLayout, bindingName) {
|
|
818
|
+
function getShaderLayoutBinding(shaderLayout, bindingName, options) {
|
|
694
819
|
const bindingLayout = shaderLayout.bindings.find(
|
|
695
820
|
(binding) => binding.name === bindingName || `${binding.name.toLocaleLowerCase()}uniforms` === bindingName.toLocaleLowerCase()
|
|
696
821
|
);
|
|
697
|
-
if (!bindingLayout) {
|
|
822
|
+
if (!bindingLayout && !options?.ignoreWarnings) {
|
|
698
823
|
import_core8.log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
699
824
|
}
|
|
700
825
|
return bindingLayout || null;
|
|
@@ -704,11 +829,21 @@ var __exports__ = (() => {
|
|
|
704
829
|
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
705
830
|
let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
|
|
706
831
|
if (bindingLayout) {
|
|
707
|
-
|
|
832
|
+
const entry = getBindGroupEntry(value, bindingLayout.location);
|
|
833
|
+
if (entry) {
|
|
834
|
+
entries.push(entry);
|
|
835
|
+
}
|
|
708
836
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
837
|
+
if (value instanceof import_core8.Texture) {
|
|
838
|
+
bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
|
|
839
|
+
ignoreWarnings: true
|
|
840
|
+
});
|
|
841
|
+
if (bindingLayout) {
|
|
842
|
+
const entry = getBindGroupEntry(value, bindingLayout.location, { sampler: true });
|
|
843
|
+
if (entry) {
|
|
844
|
+
entries.push(entry);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
712
847
|
}
|
|
713
848
|
}
|
|
714
849
|
return entries;
|
|
@@ -727,7 +862,8 @@ var __exports__ = (() => {
|
|
|
727
862
|
binding: index,
|
|
728
863
|
resource: binding.handle
|
|
729
864
|
};
|
|
730
|
-
}
|
|
865
|
+
}
|
|
866
|
+
if (binding instanceof import_core8.Texture) {
|
|
731
867
|
if (options?.sampler) {
|
|
732
868
|
return {
|
|
733
869
|
binding: index,
|
|
@@ -736,14 +872,21 @@ var __exports__ = (() => {
|
|
|
736
872
|
}
|
|
737
873
|
return {
|
|
738
874
|
binding: index,
|
|
739
|
-
resource: binding.handle
|
|
875
|
+
resource: binding.view.handle
|
|
740
876
|
};
|
|
741
877
|
}
|
|
742
|
-
|
|
878
|
+
import_core8.log.warn(`invalid binding ${name}`, binding);
|
|
879
|
+
return null;
|
|
743
880
|
}
|
|
881
|
+
var import_core8;
|
|
882
|
+
var init_get_bind_group = __esm({
|
|
883
|
+
"src/adapter/helpers/get-bind-group.ts"() {
|
|
884
|
+
"use strict";
|
|
885
|
+
import_core8 = __toESM(require_core(), 1);
|
|
886
|
+
}
|
|
887
|
+
});
|
|
744
888
|
|
|
745
889
|
// src/adapter/helpers/get-vertex-buffer-layout.ts
|
|
746
|
-
var import_core9 = __toESM(require_core(), 1);
|
|
747
890
|
function getWebGPUVertexFormat(format) {
|
|
748
891
|
if (format.endsWith("-webgl")) {
|
|
749
892
|
throw new Error(`WebGPU does not support vertex format ${format}`);
|
|
@@ -770,14 +913,14 @@ var __exports__ = (() => {
|
|
|
770
913
|
offset: attributeMapping.byteOffset,
|
|
771
914
|
shaderLocation: location
|
|
772
915
|
});
|
|
773
|
-
byteStride += (0, import_core9.
|
|
916
|
+
byteStride += (0, import_core9.getVertexFormatInfo)(format).byteLength;
|
|
774
917
|
}
|
|
775
918
|
} else {
|
|
776
919
|
const attributeLayout = findAttributeLayout(shaderLayout, mapping.name, usedAttributes);
|
|
777
920
|
if (!attributeLayout) {
|
|
778
921
|
continue;
|
|
779
922
|
}
|
|
780
|
-
byteStride = (0, import_core9.
|
|
923
|
+
byteStride = (0, import_core9.getVertexFormatInfo)(format).byteLength;
|
|
781
924
|
stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith("instance") ? "instance" : "vertex");
|
|
782
925
|
vertexAttributes.push({
|
|
783
926
|
format: getWebGPUVertexFormat(format),
|
|
@@ -795,7 +938,7 @@ var __exports__ = (() => {
|
|
|
795
938
|
for (const attribute of shaderLayout.attributes) {
|
|
796
939
|
if (!usedAttributes.has(attribute.name)) {
|
|
797
940
|
vertexBufferLayouts.push({
|
|
798
|
-
arrayStride: (0, import_core9.
|
|
941
|
+
arrayStride: (0, import_core9.getVertexFormatInfo)("float32x3").byteLength,
|
|
799
942
|
stepMode: attribute.stepMode || (attribute.name.startsWith("instance") ? "instance" : "vertex"),
|
|
800
943
|
attributes: [
|
|
801
944
|
{
|
|
@@ -814,459 +957,254 @@ var __exports__ = (() => {
|
|
|
814
957
|
});
|
|
815
958
|
return vertexBufferLayouts;
|
|
816
959
|
}
|
|
817
|
-
function findAttributeLayout(shaderLayout,
|
|
818
|
-
const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name ===
|
|
960
|
+
function findAttributeLayout(shaderLayout, name2, attributeNames) {
|
|
961
|
+
const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name2);
|
|
819
962
|
if (!attribute) {
|
|
820
|
-
import_core9.log.warn(`
|
|
963
|
+
import_core9.log.warn(`Supplied attribute not present in shader layout: ${name2}`)();
|
|
821
964
|
return null;
|
|
822
965
|
}
|
|
823
966
|
if (attributeNames) {
|
|
824
|
-
if (attributeNames.has(
|
|
825
|
-
throw new Error(`Found multiple entries for attribute: ${
|
|
967
|
+
if (attributeNames.has(name2)) {
|
|
968
|
+
throw new Error(`Found multiple entries for attribute: ${name2}`);
|
|
826
969
|
}
|
|
827
|
-
attributeNames.add(
|
|
970
|
+
attributeNames.add(name2);
|
|
828
971
|
}
|
|
829
972
|
return attribute;
|
|
830
973
|
}
|
|
974
|
+
var import_core9;
|
|
975
|
+
var init_get_vertex_buffer_layout = __esm({
|
|
976
|
+
"src/adapter/helpers/get-vertex-buffer-layout.ts"() {
|
|
977
|
+
"use strict";
|
|
978
|
+
import_core9 = __toESM(require_core(), 1);
|
|
979
|
+
}
|
|
980
|
+
});
|
|
831
981
|
|
|
832
982
|
// src/adapter/resources/webgpu-render-pipeline.ts
|
|
833
|
-
var
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
983
|
+
var import_core10, WebGPURenderPipeline;
|
|
984
|
+
var init_webgpu_render_pipeline = __esm({
|
|
985
|
+
"src/adapter/resources/webgpu-render-pipeline.ts"() {
|
|
986
|
+
"use strict";
|
|
987
|
+
import_core10 = __toESM(require_core(), 1);
|
|
988
|
+
init_webgpu_parameters();
|
|
989
|
+
init_convert_texture_format();
|
|
990
|
+
init_get_bind_group();
|
|
991
|
+
init_get_vertex_buffer_layout();
|
|
992
|
+
WebGPURenderPipeline = class extends import_core10.RenderPipeline {
|
|
993
|
+
device;
|
|
994
|
+
handle;
|
|
995
|
+
vs;
|
|
996
|
+
fs = null;
|
|
997
|
+
/** For internal use to create BindGroups */
|
|
998
|
+
_bindings;
|
|
999
|
+
_bindGroupLayout = null;
|
|
1000
|
+
_bindGroup = null;
|
|
1001
|
+
get [Symbol.toStringTag]() {
|
|
1002
|
+
return "WebGPURenderPipeline";
|
|
1003
|
+
}
|
|
1004
|
+
constructor(device, props) {
|
|
1005
|
+
super(device, props);
|
|
1006
|
+
this.device = device;
|
|
1007
|
+
this.handle = this.props.handle;
|
|
1008
|
+
if (!this.handle) {
|
|
1009
|
+
const descriptor = this._getRenderPipelineDescriptor();
|
|
1010
|
+
import_core10.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
|
|
1011
|
+
import_core10.log.probe(1, JSON.stringify(descriptor, null, 2))();
|
|
1012
|
+
import_core10.log.groupEnd(1)();
|
|
1013
|
+
this.device.pushErrorScope("validation");
|
|
1014
|
+
this.handle = this.device.handle.createRenderPipeline(descriptor);
|
|
1015
|
+
this.device.popErrorScope((error) => {
|
|
1016
|
+
this.device.reportError(new Error(`${this} creation failed:
|
|
1017
|
+
"${error.message}"`), this)();
|
|
1018
|
+
this.device.debug();
|
|
1019
|
+
});
|
|
857
1020
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
this.fs = props.fs;
|
|
863
|
-
this._bindings = { ...this.props.bindings };
|
|
864
|
-
}
|
|
865
|
-
destroy() {
|
|
866
|
-
this.handle = null;
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* @todo Use renderpass.setBindings() ?
|
|
870
|
-
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
871
|
-
*/
|
|
872
|
-
setBindings(bindings) {
|
|
873
|
-
Object.assign(this._bindings, bindings);
|
|
874
|
-
}
|
|
875
|
-
/** @todo - should this be moved to renderpass? */
|
|
876
|
-
draw(options) {
|
|
877
|
-
const webgpuRenderPass = options.renderPass;
|
|
878
|
-
this.device.handle.pushErrorScope("validation");
|
|
879
|
-
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
880
|
-
this.device.handle.popErrorScope().then((error) => {
|
|
881
|
-
if (error) {
|
|
882
|
-
import_core10.log.error(`${this} setPipeline failed:
|
|
883
|
-
"${error.message}"`, this)();
|
|
1021
|
+
this.handle.label = this.props.id;
|
|
1022
|
+
this.vs = props.vs;
|
|
1023
|
+
this.fs = props.fs;
|
|
1024
|
+
this._bindings = { ...this.props.bindings };
|
|
884
1025
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
options.firstInstance
|
|
898
|
-
);
|
|
899
|
-
} else {
|
|
900
|
-
webgpuRenderPass.handle.draw(
|
|
901
|
-
options.vertexCount || 0,
|
|
902
|
-
options.instanceCount || 1,
|
|
903
|
-
// If 0, nothing will be drawn
|
|
904
|
-
options.firstInstance
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
908
|
-
return true;
|
|
909
|
-
}
|
|
910
|
-
/** Return a bind group created by setBindings */
|
|
911
|
-
_getBindGroup() {
|
|
912
|
-
if (this.shaderLayout.bindings.length === 0) {
|
|
913
|
-
return null;
|
|
914
|
-
}
|
|
915
|
-
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
916
|
-
this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
917
|
-
return this._bindGroup;
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
921
|
-
*/
|
|
922
|
-
_getRenderPipelineDescriptor() {
|
|
923
|
-
const vertex = {
|
|
924
|
-
module: this.props.vs.handle,
|
|
925
|
-
entryPoint: this.props.vertexEntryPoint || "main",
|
|
926
|
-
buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
|
|
927
|
-
};
|
|
928
|
-
const fragment = {
|
|
929
|
-
module: this.props.fs.handle,
|
|
930
|
-
entryPoint: this.props.fragmentEntryPoint || "main",
|
|
931
|
-
targets: [
|
|
932
|
-
{
|
|
933
|
-
// TODO exclamation mark hack!
|
|
934
|
-
format: getWebGPUTextureFormat(this.device.getCanvasContext().format)
|
|
1026
|
+
destroy() {
|
|
1027
|
+
this.handle = null;
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* @todo Use renderpass.setBindings() ?
|
|
1031
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
1032
|
+
*/
|
|
1033
|
+
setBindings(bindings) {
|
|
1034
|
+
for (const [name2, binding] of Object.entries(bindings)) {
|
|
1035
|
+
if (this._bindings[name2] !== binding) {
|
|
1036
|
+
this._bindGroup = null;
|
|
1037
|
+
}
|
|
935
1038
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1039
|
+
Object.assign(this._bindings, bindings);
|
|
1040
|
+
}
|
|
1041
|
+
/** @todo - should this be moved to renderpass? */
|
|
1042
|
+
draw(options) {
|
|
1043
|
+
const webgpuRenderPass = options.renderPass;
|
|
1044
|
+
this.device.pushErrorScope("validation");
|
|
1045
|
+
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
1046
|
+
this.device.popErrorScope((error) => {
|
|
1047
|
+
this.device.reportError(new Error(`${this} setPipeline failed:
|
|
1048
|
+
"${error.message}"`), this)();
|
|
1049
|
+
this.device.debug();
|
|
1050
|
+
});
|
|
1051
|
+
const bindGroup = this._getBindGroup();
|
|
1052
|
+
if (bindGroup) {
|
|
1053
|
+
webgpuRenderPass.handle.setBindGroup(0, bindGroup);
|
|
1054
|
+
}
|
|
1055
|
+
options.vertexArray.bindBeforeRender(options.renderPass);
|
|
1056
|
+
if (options.indexCount) {
|
|
1057
|
+
webgpuRenderPass.handle.drawIndexed(
|
|
1058
|
+
options.indexCount,
|
|
1059
|
+
options.instanceCount,
|
|
1060
|
+
options.firstIndex,
|
|
1061
|
+
options.baseVertex,
|
|
1062
|
+
options.firstInstance
|
|
1063
|
+
);
|
|
1064
|
+
} else {
|
|
1065
|
+
webgpuRenderPass.handle.draw(
|
|
1066
|
+
options.vertexCount || 0,
|
|
1067
|
+
options.instanceCount || 1,
|
|
1068
|
+
// If 0, nothing will be drawn
|
|
1069
|
+
options.firstInstance
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
1073
|
+
return true;
|
|
1074
|
+
}
|
|
1075
|
+
/** Return a bind group created by setBindings */
|
|
1076
|
+
_getBindGroup() {
|
|
1077
|
+
if (this.shaderLayout.bindings.length === 0) {
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1081
|
+
this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1082
|
+
return this._bindGroup;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
1086
|
+
*/
|
|
1087
|
+
_getRenderPipelineDescriptor() {
|
|
1088
|
+
const vertex = {
|
|
1089
|
+
module: this.props.vs.handle,
|
|
1090
|
+
entryPoint: this.props.vertexEntryPoint || "main",
|
|
1091
|
+
buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
|
|
1092
|
+
};
|
|
1093
|
+
const targets = [];
|
|
1094
|
+
if (this.props.colorAttachmentFormats) {
|
|
1095
|
+
for (const format of this.props.colorAttachmentFormats) {
|
|
1096
|
+
targets.push(format ? { format: getWebGPUTextureFormat(format) } : null);
|
|
1097
|
+
}
|
|
1098
|
+
} else {
|
|
1099
|
+
targets.push({ format: getWebGPUTextureFormat(this.device.preferredColorFormat) });
|
|
1100
|
+
}
|
|
1101
|
+
const fragment = {
|
|
1102
|
+
module: this.props.fs.handle,
|
|
1103
|
+
entryPoint: this.props.fragmentEntryPoint || "main",
|
|
1104
|
+
targets
|
|
1105
|
+
};
|
|
1106
|
+
const layout = this.device.createPipelineLayout({
|
|
1107
|
+
shaderLayout: this.shaderLayout
|
|
1108
|
+
});
|
|
1109
|
+
const descriptor = {
|
|
1110
|
+
vertex,
|
|
1111
|
+
fragment,
|
|
1112
|
+
primitive: {
|
|
1113
|
+
topology: this.props.topology
|
|
1114
|
+
},
|
|
1115
|
+
layout: layout.handle
|
|
1116
|
+
};
|
|
1117
|
+
const depthFormat = this.props.depthStencilAttachmentFormat || this.device.preferredDepthFormat;
|
|
1118
|
+
if (this.props.parameters.depthWriteEnabled) {
|
|
1119
|
+
descriptor.depthStencil = {
|
|
1120
|
+
format: getWebGPUTextureFormat(depthFormat)
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
|
|
1124
|
+
return descriptor;
|
|
1125
|
+
}
|
|
948
1126
|
};
|
|
949
|
-
if (this.props.parameters.depthWriteEnabled && this.props.parameters.depthCompare) {
|
|
950
|
-
descriptor.depthStencil = {
|
|
951
|
-
format: "depth24plus",
|
|
952
|
-
depthWriteEnabled: this.props.parameters.depthWriteEnabled,
|
|
953
|
-
depthCompare: this.props.parameters.depthCompare
|
|
954
|
-
};
|
|
955
|
-
}
|
|
956
|
-
applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
|
|
957
|
-
return descriptor;
|
|
958
1127
|
}
|
|
959
|
-
};
|
|
1128
|
+
});
|
|
960
1129
|
|
|
961
1130
|
// src/adapter/resources/webgpu-framebuffer.ts
|
|
962
|
-
var import_core11
|
|
963
|
-
var
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
// src/adapter/resources/webgpu-compute-pipeline.ts
|
|
977
|
-
var import_core12 = __toESM(require_core(), 1);
|
|
978
|
-
var WebGPUComputePipeline = class extends import_core12.ComputePipeline {
|
|
979
|
-
device;
|
|
980
|
-
handle;
|
|
981
|
-
/** For internal use to create BindGroups */
|
|
982
|
-
_bindGroupLayout = null;
|
|
983
|
-
_bindGroup = null;
|
|
984
|
-
/** For internal use to create BindGroups */
|
|
985
|
-
_bindings = {};
|
|
986
|
-
constructor(device, props) {
|
|
987
|
-
super(device, props);
|
|
988
|
-
this.device = device;
|
|
989
|
-
const webgpuShader = this.props.shader;
|
|
990
|
-
this.handle = this.props.handle || this.device.handle.createComputePipeline({
|
|
991
|
-
label: this.props.id,
|
|
992
|
-
compute: {
|
|
993
|
-
module: webgpuShader.handle,
|
|
994
|
-
entryPoint: this.props.entryPoint,
|
|
995
|
-
constants: this.props.constants
|
|
996
|
-
},
|
|
997
|
-
layout: "auto"
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* @todo Use renderpass.setBindings() ?
|
|
1002
|
-
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
1003
|
-
*/
|
|
1004
|
-
setBindings(bindings) {
|
|
1005
|
-
Object.assign(this._bindings, bindings);
|
|
1006
|
-
}
|
|
1007
|
-
/** Return a bind group created by setBindings */
|
|
1008
|
-
_getBindGroup() {
|
|
1009
|
-
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1010
|
-
this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1011
|
-
return this._bindGroup;
|
|
1012
|
-
}
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
// src/adapter/resources/webgpu-render-pass.ts
|
|
1016
|
-
var import_core13 = __toESM(require_core(), 1);
|
|
1017
|
-
var WebGPURenderPass = class extends import_core13.RenderPass {
|
|
1018
|
-
device;
|
|
1019
|
-
handle;
|
|
1020
|
-
/** Active pipeline */
|
|
1021
|
-
pipeline = null;
|
|
1022
|
-
constructor(device, props = {}) {
|
|
1023
|
-
super(device, props);
|
|
1024
|
-
this.device = device;
|
|
1025
|
-
const framebuffer = props.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
|
|
1026
|
-
const renderPassDescriptor = this.getRenderPassDescriptor(framebuffer);
|
|
1027
|
-
const webgpuQuerySet = props.timestampQuerySet;
|
|
1028
|
-
if (webgpuQuerySet) {
|
|
1029
|
-
renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
|
|
1030
|
-
}
|
|
1031
|
-
if (device.features.has("timestamp-query")) {
|
|
1032
|
-
const webgpuTSQuerySet = props.timestampQuerySet;
|
|
1033
|
-
renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
|
|
1034
|
-
querySet: webgpuTSQuerySet.handle,
|
|
1035
|
-
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
1036
|
-
endOfPassWriteIndex: props.endTimestampIndex
|
|
1037
|
-
} : void 0;
|
|
1038
|
-
}
|
|
1039
|
-
if (!device.commandEncoder) {
|
|
1040
|
-
throw new Error("commandEncoder not available");
|
|
1041
|
-
}
|
|
1042
|
-
this.device.handle.pushErrorScope("validation");
|
|
1043
|
-
this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
1044
|
-
this.device.handle.popErrorScope().then((error) => {
|
|
1045
|
-
if (error) {
|
|
1046
|
-
import_core13.log.error(`${this} creation failed:
|
|
1047
|
-
"${error.message}"`, this)();
|
|
1048
|
-
}
|
|
1049
|
-
});
|
|
1050
|
-
this.handle.label = this.props.id;
|
|
1051
|
-
import_core13.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
|
|
1052
|
-
import_core13.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
|
|
1053
|
-
import_core13.log.groupEnd(3)();
|
|
1054
|
-
}
|
|
1055
|
-
destroy() {
|
|
1056
|
-
}
|
|
1057
|
-
end() {
|
|
1058
|
-
this.handle.end();
|
|
1059
|
-
}
|
|
1060
|
-
setPipeline(pipeline) {
|
|
1061
|
-
this.pipeline = pipeline;
|
|
1062
|
-
this.handle.setPipeline(this.pipeline.handle);
|
|
1063
|
-
}
|
|
1064
|
-
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
1065
|
-
setBindings(bindings) {
|
|
1066
|
-
this.pipeline?.setBindings(bindings);
|
|
1067
|
-
const bindGroup = this.pipeline?._getBindGroup();
|
|
1068
|
-
if (bindGroup) {
|
|
1069
|
-
this.handle.setBindGroup(0, bindGroup);
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
setIndexBuffer(buffer, indexFormat, offset = 0, size) {
|
|
1073
|
-
this.handle.setIndexBuffer(buffer.handle, indexFormat, offset, size);
|
|
1074
|
-
}
|
|
1075
|
-
setVertexBuffer(slot, buffer, offset = 0) {
|
|
1076
|
-
this.handle.setVertexBuffer(slot, buffer.handle, offset);
|
|
1077
|
-
}
|
|
1078
|
-
draw(options) {
|
|
1079
|
-
if (options.indexCount) {
|
|
1080
|
-
this.handle.drawIndexed(
|
|
1081
|
-
options.indexCount,
|
|
1082
|
-
options.instanceCount,
|
|
1083
|
-
options.firstIndex,
|
|
1084
|
-
options.baseVertex,
|
|
1085
|
-
options.firstInstance
|
|
1086
|
-
);
|
|
1087
|
-
} else {
|
|
1088
|
-
this.handle.draw(
|
|
1089
|
-
options.vertexCount || 0,
|
|
1090
|
-
options.instanceCount || 1,
|
|
1091
|
-
options.firstIndex,
|
|
1092
|
-
options.firstInstance
|
|
1093
|
-
);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
drawIndirect() {
|
|
1097
|
-
}
|
|
1098
|
-
setParameters(parameters) {
|
|
1099
|
-
const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
|
|
1100
|
-
if (blendConstant) {
|
|
1101
|
-
this.handle.setBlendConstant(blendConstant);
|
|
1102
|
-
}
|
|
1103
|
-
if (stencilReference) {
|
|
1104
|
-
this.handle.setStencilReference(stencilReference);
|
|
1105
|
-
}
|
|
1106
|
-
if (scissorRect) {
|
|
1107
|
-
this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
|
|
1108
|
-
}
|
|
1109
|
-
if (viewport) {
|
|
1110
|
-
this.handle.setViewport(
|
|
1111
|
-
viewport[0],
|
|
1112
|
-
viewport[1],
|
|
1113
|
-
viewport[2],
|
|
1114
|
-
viewport[3],
|
|
1115
|
-
viewport[4] ?? 0,
|
|
1116
|
-
viewport[5] ?? 1
|
|
1117
|
-
);
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
pushDebugGroup(groupLabel) {
|
|
1121
|
-
this.handle.pushDebugGroup(groupLabel);
|
|
1122
|
-
}
|
|
1123
|
-
popDebugGroup() {
|
|
1124
|
-
this.handle.popDebugGroup();
|
|
1125
|
-
}
|
|
1126
|
-
insertDebugMarker(markerLabel) {
|
|
1127
|
-
this.handle.insertDebugMarker(markerLabel);
|
|
1128
|
-
}
|
|
1129
|
-
beginOcclusionQuery(queryIndex) {
|
|
1130
|
-
this.handle.beginOcclusionQuery(queryIndex);
|
|
1131
|
-
}
|
|
1132
|
-
endOcclusionQuery() {
|
|
1133
|
-
this.handle.endOcclusionQuery();
|
|
1134
|
-
}
|
|
1135
|
-
// executeBundles(bundles: Iterable<GPURenderBundle>): void;
|
|
1136
|
-
// INTERNAL
|
|
1137
|
-
/**
|
|
1138
|
-
* Partial render pass descriptor. Used by WebGPURenderPass.
|
|
1139
|
-
* @returns attachments fields of a renderpass descriptor.
|
|
1140
|
-
*/
|
|
1141
|
-
getRenderPassDescriptor(framebuffer) {
|
|
1142
|
-
const renderPassDescriptor = {
|
|
1143
|
-
colorAttachments: []
|
|
1144
|
-
};
|
|
1145
|
-
renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map(
|
|
1146
|
-
(colorAttachment, index) => ({
|
|
1147
|
-
// clear values
|
|
1148
|
-
loadOp: this.props.clearColor !== false ? "clear" : "load",
|
|
1149
|
-
clearValue: convertColor(
|
|
1150
|
-
this.props.clearColors?.[index] || this.props.clearColor || import_core13.RenderPass.defaultClearColor
|
|
1151
|
-
),
|
|
1152
|
-
storeOp: this.props.discard ? "discard" : "store",
|
|
1153
|
-
// ...colorAttachment,
|
|
1154
|
-
view: colorAttachment.handle
|
|
1155
|
-
})
|
|
1156
|
-
);
|
|
1157
|
-
if (framebuffer.depthStencilAttachment) {
|
|
1158
|
-
renderPassDescriptor.depthStencilAttachment = {
|
|
1159
|
-
view: framebuffer.depthStencilAttachment.handle
|
|
1160
|
-
};
|
|
1161
|
-
const { depthStencilAttachment } = renderPassDescriptor;
|
|
1162
|
-
if (this.props.depthReadOnly) {
|
|
1163
|
-
depthStencilAttachment.depthReadOnly = true;
|
|
1164
|
-
}
|
|
1165
|
-
if (this.props.clearDepth !== false) {
|
|
1166
|
-
depthStencilAttachment.depthClearValue = this.props.clearDepth;
|
|
1131
|
+
var import_core11, WebGPUFramebuffer;
|
|
1132
|
+
var init_webgpu_framebuffer = __esm({
|
|
1133
|
+
"src/adapter/resources/webgpu-framebuffer.ts"() {
|
|
1134
|
+
"use strict";
|
|
1135
|
+
import_core11 = __toESM(require_core(), 1);
|
|
1136
|
+
WebGPUFramebuffer = class extends import_core11.Framebuffer {
|
|
1137
|
+
device;
|
|
1138
|
+
handle = null;
|
|
1139
|
+
colorAttachments = [];
|
|
1140
|
+
depthStencilAttachment = null;
|
|
1141
|
+
constructor(device, props) {
|
|
1142
|
+
super(device, props);
|
|
1143
|
+
this.device = device;
|
|
1144
|
+
this.autoCreateAttachmentTextures();
|
|
1167
1145
|
}
|
|
1168
|
-
|
|
1169
|
-
if (hasDepthAspect) {
|
|
1170
|
-
depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
|
|
1171
|
-
depthStencilAttachment.depthStoreOp = "store";
|
|
1146
|
+
updateAttachments() {
|
|
1172
1147
|
}
|
|
1173
|
-
|
|
1174
|
-
if (hasStencilAspect) {
|
|
1175
|
-
depthStencilAttachment.stencilLoadOp = this.props.clearStencil !== false ? "clear" : "load";
|
|
1176
|
-
depthStencilAttachment.stencilStoreOp = "store";
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
return renderPassDescriptor;
|
|
1148
|
+
};
|
|
1180
1149
|
}
|
|
1181
|
-
};
|
|
1182
|
-
function convertColor(color) {
|
|
1183
|
-
return { r: color[0], g: color[1], b: color[2], a: color[3] };
|
|
1184
|
-
}
|
|
1150
|
+
});
|
|
1185
1151
|
|
|
1186
|
-
// src/adapter/resources/webgpu-compute-
|
|
1187
|
-
var
|
|
1188
|
-
var
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1152
|
+
// src/adapter/resources/webgpu-compute-pipeline.ts
|
|
1153
|
+
var import_core12, WebGPUComputePipeline;
|
|
1154
|
+
var init_webgpu_compute_pipeline = __esm({
|
|
1155
|
+
"src/adapter/resources/webgpu-compute-pipeline.ts"() {
|
|
1156
|
+
"use strict";
|
|
1157
|
+
import_core12 = __toESM(require_core(), 1);
|
|
1158
|
+
init_get_bind_group();
|
|
1159
|
+
WebGPUComputePipeline = class extends import_core12.ComputePipeline {
|
|
1160
|
+
device;
|
|
1161
|
+
handle;
|
|
1162
|
+
/** For internal use to create BindGroups */
|
|
1163
|
+
_bindGroupLayout = null;
|
|
1164
|
+
_bindGroup = null;
|
|
1165
|
+
/** For internal use to create BindGroups */
|
|
1166
|
+
_bindings = {};
|
|
1167
|
+
constructor(device, props) {
|
|
1168
|
+
super(device, props);
|
|
1169
|
+
this.device = device;
|
|
1170
|
+
const webgpuShader = this.props.shader;
|
|
1171
|
+
this.handle = this.props.handle || this.device.handle.createComputePipeline({
|
|
1172
|
+
label: this.props.id,
|
|
1173
|
+
compute: {
|
|
1174
|
+
module: webgpuShader.handle,
|
|
1175
|
+
entryPoint: this.props.entryPoint,
|
|
1176
|
+
constants: this.props.constants
|
|
1177
|
+
},
|
|
1178
|
+
layout: "auto"
|
|
1179
|
+
});
|
|
1204
1180
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
this.handle.setPipeline(wgpuPipeline.handle);
|
|
1220
|
-
this._webgpuPipeline = wgpuPipeline;
|
|
1221
|
-
this.setBindings([]);
|
|
1222
|
-
}
|
|
1223
|
-
/**
|
|
1224
|
-
* Sets an array of bindings (uniform buffers, samplers, textures, ...)
|
|
1225
|
-
* TODO - still some API confusion - does this method go here or on the pipeline?
|
|
1226
|
-
*/
|
|
1227
|
-
setBindings(bindings) {
|
|
1228
|
-
const bindGroup = this._webgpuPipeline._getBindGroup();
|
|
1229
|
-
this.handle.setBindGroup(0, bindGroup);
|
|
1230
|
-
}
|
|
1231
|
-
/**
|
|
1232
|
-
* Dispatch work to be performed with the current ComputePipeline.
|
|
1233
|
-
* @param x X dimension of the grid of work groups to dispatch.
|
|
1234
|
-
* @param y Y dimension of the grid of work groups to dispatch.
|
|
1235
|
-
* @param z Z dimension of the grid of work groups to dispatch.
|
|
1236
|
-
*/
|
|
1237
|
-
dispatch(x, y, z) {
|
|
1238
|
-
this.handle.dispatchWorkgroups(x, y, z);
|
|
1239
|
-
}
|
|
1240
|
-
/**
|
|
1241
|
-
* Dispatch work to be performed with the current ComputePipeline.
|
|
1242
|
-
*
|
|
1243
|
-
* 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()
|
|
1244
|
-
* @param indirectBuffer
|
|
1245
|
-
* @param indirectOffset offset in buffer to the beginning of the dispatch data.
|
|
1246
|
-
*/
|
|
1247
|
-
dispatchIndirect(indirectBuffer, indirectByteOffset = 0) {
|
|
1248
|
-
const webgpuBuffer = indirectBuffer;
|
|
1249
|
-
this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
|
|
1250
|
-
}
|
|
1251
|
-
pushDebugGroup(groupLabel) {
|
|
1252
|
-
this.handle.pushDebugGroup(groupLabel);
|
|
1253
|
-
}
|
|
1254
|
-
popDebugGroup() {
|
|
1255
|
-
this.handle.popDebugGroup();
|
|
1256
|
-
}
|
|
1257
|
-
insertDebugMarker(markerLabel) {
|
|
1258
|
-
this.handle.insertDebugMarker(markerLabel);
|
|
1181
|
+
/**
|
|
1182
|
+
* @todo Use renderpass.setBindings() ?
|
|
1183
|
+
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
1184
|
+
*/
|
|
1185
|
+
setBindings(bindings) {
|
|
1186
|
+
Object.assign(this._bindings, bindings);
|
|
1187
|
+
}
|
|
1188
|
+
/** Return a bind group created by setBindings */
|
|
1189
|
+
_getBindGroup() {
|
|
1190
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1191
|
+
this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1192
|
+
return this._bindGroup;
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1259
1195
|
}
|
|
1260
|
-
};
|
|
1261
|
-
|
|
1262
|
-
// src/adapter/resources/webgpu-vertex-array.ts
|
|
1263
|
-
var import_core15 = __toESM(require_core(), 1);
|
|
1196
|
+
});
|
|
1264
1197
|
|
|
1265
1198
|
// ../../node_modules/@probe.gl/env/dist/lib/globals.js
|
|
1266
|
-
var document_
|
|
1267
|
-
var
|
|
1268
|
-
|
|
1269
|
-
|
|
1199
|
+
var document_, process_, console_, navigator_;
|
|
1200
|
+
var init_globals = __esm({
|
|
1201
|
+
"../../node_modules/@probe.gl/env/dist/lib/globals.js"() {
|
|
1202
|
+
document_ = globalThis.document || {};
|
|
1203
|
+
process_ = globalThis.process || {};
|
|
1204
|
+
console_ = globalThis.console;
|
|
1205
|
+
navigator_ = globalThis.navigator || {};
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1270
1208
|
|
|
1271
1209
|
// ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
|
|
1272
1210
|
function isElectron(mockUserAgent) {
|
|
@@ -1280,6 +1218,10 @@ var __exports__ = (() => {
|
|
|
1280
1218
|
const userAgent = mockUserAgent || realUserAgent;
|
|
1281
1219
|
return Boolean(userAgent && userAgent.indexOf("Electron") >= 0);
|
|
1282
1220
|
}
|
|
1221
|
+
var init_is_electron = __esm({
|
|
1222
|
+
"../../node_modules/@probe.gl/env/dist/lib/is-electron.js"() {
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1283
1225
|
|
|
1284
1226
|
// ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
|
|
1285
1227
|
function isBrowser() {
|
|
@@ -1289,6 +1231,11 @@ var __exports__ = (() => {
|
|
|
1289
1231
|
);
|
|
1290
1232
|
return !isNode || isElectron();
|
|
1291
1233
|
}
|
|
1234
|
+
var init_is_browser = __esm({
|
|
1235
|
+
"../../node_modules/@probe.gl/env/dist/lib/is-browser.js"() {
|
|
1236
|
+
init_is_electron();
|
|
1237
|
+
}
|
|
1238
|
+
});
|
|
1292
1239
|
|
|
1293
1240
|
// ../../node_modules/@probe.gl/env/dist/lib/get-browser.js
|
|
1294
1241
|
function getBrowser(mockUserAgent) {
|
|
@@ -1313,561 +1260,1013 @@ var __exports__ = (() => {
|
|
|
1313
1260
|
}
|
|
1314
1261
|
return "Unknown";
|
|
1315
1262
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
}
|
|
1322
|
-
device;
|
|
1323
|
-
/** Vertex Array is a helper class under WebGPU */
|
|
1324
|
-
handle;
|
|
1325
|
-
// Create a VertexArray
|
|
1326
|
-
constructor(device, props) {
|
|
1327
|
-
super(device, props);
|
|
1328
|
-
this.device = device;
|
|
1329
|
-
}
|
|
1330
|
-
destroy() {
|
|
1331
|
-
}
|
|
1332
|
-
/**
|
|
1333
|
-
* Set an elements buffer, for indexed rendering.
|
|
1334
|
-
* Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
|
|
1335
|
-
*/
|
|
1336
|
-
setIndexBuffer(buffer) {
|
|
1337
|
-
this.indexBuffer = buffer;
|
|
1263
|
+
var init_get_browser = __esm({
|
|
1264
|
+
"../../node_modules/@probe.gl/env/dist/lib/get-browser.js"() {
|
|
1265
|
+
init_is_browser();
|
|
1266
|
+
init_is_electron();
|
|
1267
|
+
init_globals();
|
|
1338
1268
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
// ../../node_modules/@probe.gl/env/dist/index.js
|
|
1272
|
+
var init_dist = __esm({
|
|
1273
|
+
"../../node_modules/@probe.gl/env/dist/index.js"() {
|
|
1274
|
+
init_get_browser();
|
|
1342
1275
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
// @ts-expect-error TODO - we must enforce type
|
|
1356
|
-
webgpuIndexBuffer?.indexType
|
|
1357
|
-
);
|
|
1358
|
-
}
|
|
1359
|
-
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
1360
|
-
const webgpuBuffer = this.attributes[location];
|
|
1361
|
-
if (webgpuBuffer?.handle) {
|
|
1362
|
-
import_core15.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer?.handle)();
|
|
1363
|
-
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
// src/adapter/resources/webgpu-vertex-array.ts
|
|
1279
|
+
var import_core13, WebGPUVertexArray;
|
|
1280
|
+
var init_webgpu_vertex_array = __esm({
|
|
1281
|
+
"src/adapter/resources/webgpu-vertex-array.ts"() {
|
|
1282
|
+
"use strict";
|
|
1283
|
+
import_core13 = __toESM(require_core(), 1);
|
|
1284
|
+
init_dist();
|
|
1285
|
+
WebGPUVertexArray = class extends import_core13.VertexArray {
|
|
1286
|
+
get [Symbol.toStringTag]() {
|
|
1287
|
+
return "WebGPUVertexArray";
|
|
1364
1288
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1289
|
+
device;
|
|
1290
|
+
/** Vertex Array is just a helper class under WebGPU */
|
|
1291
|
+
handle = null;
|
|
1292
|
+
// Create a VertexArray
|
|
1293
|
+
constructor(device, props) {
|
|
1294
|
+
super(device, props);
|
|
1295
|
+
this.device = device;
|
|
1296
|
+
}
|
|
1297
|
+
destroy() {
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Set an elements buffer, for indexed rendering.
|
|
1301
|
+
* Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
|
|
1302
|
+
*/
|
|
1303
|
+
setIndexBuffer(buffer) {
|
|
1304
|
+
this.indexBuffer = buffer;
|
|
1305
|
+
}
|
|
1306
|
+
/** Set a bufferSlot in vertex attributes array to a buffer, enables the bufferSlot, sets divisor */
|
|
1307
|
+
setBuffer(bufferSlot, buffer) {
|
|
1308
|
+
this.attributes[bufferSlot] = buffer;
|
|
1309
|
+
}
|
|
1310
|
+
bindBeforeRender(renderPass, firstIndex, indexCount) {
|
|
1311
|
+
const webgpuRenderPass = renderPass;
|
|
1312
|
+
const webgpuIndexBuffer = this.indexBuffer;
|
|
1313
|
+
if (webgpuIndexBuffer?.handle) {
|
|
1314
|
+
import_core13.log.info(
|
|
1315
|
+
3,
|
|
1316
|
+
"setting index buffer",
|
|
1317
|
+
webgpuIndexBuffer?.handle,
|
|
1318
|
+
webgpuIndexBuffer?.indexType
|
|
1319
|
+
)();
|
|
1320
|
+
webgpuRenderPass.handle.setIndexBuffer(
|
|
1321
|
+
webgpuIndexBuffer?.handle,
|
|
1322
|
+
// @ts-expect-error TODO - we must enforce type
|
|
1323
|
+
webgpuIndexBuffer?.indexType
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
1327
|
+
const webgpuBuffer = this.attributes[location];
|
|
1328
|
+
if (webgpuBuffer?.handle) {
|
|
1329
|
+
import_core13.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer?.handle)();
|
|
1330
|
+
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
unbindAfterRender(renderPass) {
|
|
1335
|
+
}
|
|
1336
|
+
// DEPRECATED METHODS
|
|
1337
|
+
/**
|
|
1338
|
+
* @deprecated is this even an issue for WebGPU?
|
|
1339
|
+
* Attribute 0 can not be disable on most desktop OpenGL based browsers
|
|
1340
|
+
*/
|
|
1341
|
+
static isConstantAttributeZeroSupported(device) {
|
|
1342
|
+
return getBrowser() === "Chrome";
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1376
1345
|
}
|
|
1377
|
-
};
|
|
1346
|
+
});
|
|
1378
1347
|
|
|
1379
1348
|
// src/adapter/webgpu-canvas-context.ts
|
|
1380
|
-
var
|
|
1381
|
-
var
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1349
|
+
var import_core14, WebGPUCanvasContext;
|
|
1350
|
+
var init_webgpu_canvas_context = __esm({
|
|
1351
|
+
"src/adapter/webgpu-canvas-context.ts"() {
|
|
1352
|
+
"use strict";
|
|
1353
|
+
import_core14 = __toESM(require_core(), 1);
|
|
1354
|
+
init_webgpu_framebuffer();
|
|
1355
|
+
WebGPUCanvasContext = class extends import_core14.CanvasContext {
|
|
1356
|
+
device;
|
|
1357
|
+
handle;
|
|
1358
|
+
depthStencilAttachment = null;
|
|
1359
|
+
get [Symbol.toStringTag]() {
|
|
1360
|
+
return "WebGPUCanvasContext";
|
|
1361
|
+
}
|
|
1362
|
+
constructor(device, adapter, props) {
|
|
1363
|
+
super(props);
|
|
1364
|
+
const context = this.canvas.getContext("webgpu");
|
|
1365
|
+
if (!context) {
|
|
1366
|
+
throw new Error(`${this}: Failed to create WebGPU canvas context`);
|
|
1367
|
+
}
|
|
1368
|
+
this.device = device;
|
|
1369
|
+
this.handle = context;
|
|
1370
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
1371
|
+
this._updateDevice();
|
|
1372
|
+
}
|
|
1373
|
+
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
1374
|
+
destroy() {
|
|
1375
|
+
this.handle.unconfigure();
|
|
1376
|
+
super.destroy();
|
|
1377
|
+
}
|
|
1378
|
+
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
1379
|
+
getCurrentFramebuffer(options = {
|
|
1380
|
+
depthStencilFormat: "depth24plus"
|
|
1381
|
+
}) {
|
|
1382
|
+
const currentColorAttachment = this.getCurrentTexture();
|
|
1383
|
+
if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
|
|
1384
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
1385
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
1386
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
1387
|
+
import_core14.log.log(
|
|
1388
|
+
1,
|
|
1389
|
+
`${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`
|
|
1390
|
+
)();
|
|
1391
|
+
}
|
|
1392
|
+
if (options?.depthStencilFormat) {
|
|
1393
|
+
this._createDepthStencilAttachment(options?.depthStencilFormat);
|
|
1394
|
+
}
|
|
1395
|
+
return new WebGPUFramebuffer(this.device, {
|
|
1396
|
+
colorAttachments: [currentColorAttachment],
|
|
1397
|
+
depthStencilAttachment: this.depthStencilAttachment
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
// IMPLEMENTATION OF ABSTRACT METHODS
|
|
1401
|
+
_updateDevice() {
|
|
1402
|
+
if (this.depthStencilAttachment) {
|
|
1403
|
+
this.depthStencilAttachment.destroy();
|
|
1404
|
+
this.depthStencilAttachment = null;
|
|
1405
|
+
}
|
|
1406
|
+
this.handle.configure({
|
|
1407
|
+
device: this.device.handle,
|
|
1408
|
+
format: this.device.preferredColorFormat,
|
|
1409
|
+
// Can be used to define e.g. -srgb views
|
|
1410
|
+
// viewFormats: [...]
|
|
1411
|
+
colorSpace: this.props.colorSpace,
|
|
1412
|
+
alphaMode: this.props.alphaMode
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
/** Wrap the current canvas context texture in a luma.gl texture */
|
|
1416
|
+
getCurrentTexture() {
|
|
1417
|
+
const handle = this.handle.getCurrentTexture();
|
|
1418
|
+
return this.device.createTexture({
|
|
1419
|
+
id: `${this.id}#color-texture`,
|
|
1420
|
+
handle,
|
|
1421
|
+
format: this.device.preferredColorFormat,
|
|
1422
|
+
width: handle.width,
|
|
1423
|
+
height: handle.height
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
1427
|
+
_createDepthStencilAttachment(depthStencilFormat) {
|
|
1428
|
+
if (!this.depthStencilAttachment) {
|
|
1429
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
1430
|
+
id: `${this.id}#depth-stencil-texture`,
|
|
1431
|
+
usage: import_core14.Texture.RENDER_ATTACHMENT,
|
|
1432
|
+
format: depthStencilFormat,
|
|
1433
|
+
width: this.drawingBufferWidth,
|
|
1434
|
+
height: this.drawingBufferHeight
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
return this.depthStencilAttachment;
|
|
1438
|
+
}
|
|
1439
|
+
};
|
|
1416
1440
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
alphaMode: this.props.alphaMode
|
|
1437
|
-
});
|
|
1438
|
-
import_core16.log.log(1, `${this} Resized ${oldWidth}x${oldHeight} => ${newWidth}x${newHeight}px`)();
|
|
1439
|
-
}
|
|
1441
|
+
});
|
|
1442
|
+
|
|
1443
|
+
// src/adapter/resources/webgpu-command-buffer.ts
|
|
1444
|
+
var import_core15, WebGPUCommandBuffer;
|
|
1445
|
+
var init_webgpu_command_buffer = __esm({
|
|
1446
|
+
"src/adapter/resources/webgpu-command-buffer.ts"() {
|
|
1447
|
+
"use strict";
|
|
1448
|
+
import_core15 = __toESM(require_core(), 1);
|
|
1449
|
+
WebGPUCommandBuffer = class extends import_core15.CommandBuffer {
|
|
1450
|
+
device;
|
|
1451
|
+
handle;
|
|
1452
|
+
constructor(commandEncoder, props) {
|
|
1453
|
+
super(commandEncoder.device, {});
|
|
1454
|
+
this.device = commandEncoder.device;
|
|
1455
|
+
this.handle = this.props.handle || commandEncoder.handle.finish({
|
|
1456
|
+
label: props?.id || "unnamed-command-buffer"
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1440
1460
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1463
|
+
// src/adapter/resources/webgpu-render-pass.ts
|
|
1464
|
+
function convertColor(color) {
|
|
1465
|
+
return { r: color[0], g: color[1], b: color[2], a: color[3] };
|
|
1466
|
+
}
|
|
1467
|
+
var import_core16, WebGPURenderPass;
|
|
1468
|
+
var init_webgpu_render_pass = __esm({
|
|
1469
|
+
"src/adapter/resources/webgpu-render-pass.ts"() {
|
|
1470
|
+
"use strict";
|
|
1471
|
+
import_core16 = __toESM(require_core(), 1);
|
|
1472
|
+
WebGPURenderPass = class extends import_core16.RenderPass {
|
|
1473
|
+
device;
|
|
1474
|
+
handle;
|
|
1475
|
+
/** Active pipeline */
|
|
1476
|
+
pipeline = null;
|
|
1477
|
+
constructor(device, props = {}) {
|
|
1478
|
+
super(device, props);
|
|
1479
|
+
this.device = device;
|
|
1480
|
+
const framebuffer = props.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
|
|
1481
|
+
const renderPassDescriptor = this.getRenderPassDescriptor(framebuffer);
|
|
1482
|
+
const webgpuQuerySet = props.timestampQuerySet;
|
|
1483
|
+
if (webgpuQuerySet) {
|
|
1484
|
+
renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
|
|
1485
|
+
}
|
|
1486
|
+
if (device.features.has("timestamp-query")) {
|
|
1487
|
+
const webgpuTSQuerySet = props.timestampQuerySet;
|
|
1488
|
+
renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
|
|
1489
|
+
querySet: webgpuTSQuerySet.handle,
|
|
1490
|
+
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
1491
|
+
endOfPassWriteIndex: props.endTimestampIndex
|
|
1492
|
+
} : void 0;
|
|
1493
|
+
}
|
|
1494
|
+
if (!device.commandEncoder) {
|
|
1495
|
+
throw new Error("commandEncoder not available");
|
|
1496
|
+
}
|
|
1497
|
+
this.device.pushErrorScope("validation");
|
|
1498
|
+
this.handle = this.props.handle || device.commandEncoder.handle.beginRenderPass(renderPassDescriptor);
|
|
1499
|
+
this.device.popErrorScope((error) => {
|
|
1500
|
+
this.device.reportError(new Error(`${this} creation failed:
|
|
1501
|
+
"${error.message}"`), this)();
|
|
1502
|
+
this.device.debug();
|
|
1503
|
+
});
|
|
1504
|
+
this.handle.label = this.props.id;
|
|
1505
|
+
import_core16.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
|
|
1506
|
+
import_core16.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
|
|
1507
|
+
import_core16.log.groupEnd(3)();
|
|
1508
|
+
}
|
|
1509
|
+
destroy() {
|
|
1510
|
+
}
|
|
1511
|
+
end() {
|
|
1512
|
+
this.handle.end();
|
|
1513
|
+
}
|
|
1514
|
+
setPipeline(pipeline) {
|
|
1515
|
+
this.pipeline = pipeline;
|
|
1516
|
+
this.device.pushErrorScope("validation");
|
|
1517
|
+
this.handle.setPipeline(this.pipeline.handle);
|
|
1518
|
+
this.device.popErrorScope((error) => {
|
|
1519
|
+
this.device.reportError(new Error(`${this} setPipeline failed:
|
|
1520
|
+
"${error.message}"`), this)();
|
|
1521
|
+
this.device.debug();
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
1525
|
+
setBindings(bindings) {
|
|
1526
|
+
this.pipeline?.setBindings(bindings);
|
|
1527
|
+
const bindGroup = this.pipeline?._getBindGroup();
|
|
1528
|
+
if (bindGroup) {
|
|
1529
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
setIndexBuffer(buffer, indexFormat, offset = 0, size) {
|
|
1533
|
+
this.handle.setIndexBuffer(buffer.handle, indexFormat, offset, size);
|
|
1534
|
+
}
|
|
1535
|
+
setVertexBuffer(slot, buffer, offset = 0) {
|
|
1536
|
+
this.handle.setVertexBuffer(slot, buffer.handle, offset);
|
|
1537
|
+
}
|
|
1538
|
+
draw(options) {
|
|
1539
|
+
if (options.indexCount) {
|
|
1540
|
+
this.handle.drawIndexed(
|
|
1541
|
+
options.indexCount,
|
|
1542
|
+
options.instanceCount,
|
|
1543
|
+
options.firstIndex,
|
|
1544
|
+
options.baseVertex,
|
|
1545
|
+
options.firstInstance
|
|
1546
|
+
);
|
|
1547
|
+
} else {
|
|
1548
|
+
this.handle.draw(
|
|
1549
|
+
options.vertexCount || 0,
|
|
1550
|
+
options.instanceCount || 1,
|
|
1551
|
+
options.firstIndex,
|
|
1552
|
+
options.firstInstance
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
drawIndirect() {
|
|
1557
|
+
}
|
|
1558
|
+
setParameters(parameters) {
|
|
1559
|
+
const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
|
|
1560
|
+
if (blendConstant) {
|
|
1561
|
+
this.handle.setBlendConstant(blendConstant);
|
|
1562
|
+
}
|
|
1563
|
+
if (stencilReference) {
|
|
1564
|
+
this.handle.setStencilReference(stencilReference);
|
|
1565
|
+
}
|
|
1566
|
+
if (scissorRect) {
|
|
1567
|
+
this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
|
|
1568
|
+
}
|
|
1569
|
+
if (viewport) {
|
|
1570
|
+
this.handle.setViewport(
|
|
1571
|
+
viewport[0],
|
|
1572
|
+
viewport[1],
|
|
1573
|
+
viewport[2],
|
|
1574
|
+
viewport[3],
|
|
1575
|
+
viewport[4] ?? 0,
|
|
1576
|
+
viewport[5] ?? 1
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
pushDebugGroup(groupLabel) {
|
|
1581
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1582
|
+
}
|
|
1583
|
+
popDebugGroup() {
|
|
1584
|
+
this.handle.popDebugGroup();
|
|
1585
|
+
}
|
|
1586
|
+
insertDebugMarker(markerLabel) {
|
|
1587
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1588
|
+
}
|
|
1589
|
+
beginOcclusionQuery(queryIndex) {
|
|
1590
|
+
this.handle.beginOcclusionQuery(queryIndex);
|
|
1591
|
+
}
|
|
1592
|
+
endOcclusionQuery() {
|
|
1593
|
+
this.handle.endOcclusionQuery();
|
|
1594
|
+
}
|
|
1595
|
+
// executeBundles(bundles: Iterable<GPURenderBundle>): void;
|
|
1596
|
+
// INTERNAL
|
|
1597
|
+
/**
|
|
1598
|
+
* Partial render pass descriptor. Used by WebGPURenderPass.
|
|
1599
|
+
* @returns attachments fields of a renderpass descriptor.
|
|
1600
|
+
*/
|
|
1601
|
+
getRenderPassDescriptor(framebuffer) {
|
|
1602
|
+
const renderPassDescriptor = {
|
|
1603
|
+
colorAttachments: []
|
|
1604
|
+
};
|
|
1605
|
+
renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map(
|
|
1606
|
+
(colorAttachment, index) => ({
|
|
1607
|
+
// clear values
|
|
1608
|
+
loadOp: this.props.clearColor !== false ? "clear" : "load",
|
|
1609
|
+
clearValue: convertColor(
|
|
1610
|
+
this.props.clearColors?.[index] || this.props.clearColor || import_core16.RenderPass.defaultClearColor
|
|
1611
|
+
),
|
|
1612
|
+
storeOp: this.props.discard ? "discard" : "store",
|
|
1613
|
+
// ...colorAttachment,
|
|
1614
|
+
view: colorAttachment.handle
|
|
1615
|
+
})
|
|
1616
|
+
);
|
|
1617
|
+
if (framebuffer.depthStencilAttachment) {
|
|
1618
|
+
renderPassDescriptor.depthStencilAttachment = {
|
|
1619
|
+
view: framebuffer.depthStencilAttachment.handle
|
|
1620
|
+
};
|
|
1621
|
+
const { depthStencilAttachment } = renderPassDescriptor;
|
|
1622
|
+
if (this.props.depthReadOnly) {
|
|
1623
|
+
depthStencilAttachment.depthReadOnly = true;
|
|
1624
|
+
}
|
|
1625
|
+
if (this.props.clearDepth !== false) {
|
|
1626
|
+
depthStencilAttachment.depthClearValue = this.props.clearDepth;
|
|
1627
|
+
}
|
|
1628
|
+
const hasDepthAspect = true;
|
|
1629
|
+
if (hasDepthAspect) {
|
|
1630
|
+
depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
|
|
1631
|
+
depthStencilAttachment.depthStoreOp = "store";
|
|
1632
|
+
}
|
|
1633
|
+
const hasStencilAspect = false;
|
|
1634
|
+
if (hasStencilAspect) {
|
|
1635
|
+
depthStencilAttachment.stencilLoadOp = this.props.clearStencil !== false ? "clear" : "load";
|
|
1636
|
+
depthStencilAttachment.stencilStoreOp = "store";
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
return renderPassDescriptor;
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1450
1642
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1643
|
+
});
|
|
1644
|
+
|
|
1645
|
+
// src/adapter/resources/webgpu-compute-pass.ts
|
|
1646
|
+
var import_core17, WebGPUComputePass;
|
|
1647
|
+
var init_webgpu_compute_pass = __esm({
|
|
1648
|
+
"src/adapter/resources/webgpu-compute-pass.ts"() {
|
|
1649
|
+
"use strict";
|
|
1650
|
+
import_core17 = __toESM(require_core(), 1);
|
|
1651
|
+
WebGPUComputePass = class extends import_core17.ComputePass {
|
|
1652
|
+
device;
|
|
1653
|
+
handle;
|
|
1654
|
+
_webgpuPipeline = null;
|
|
1655
|
+
constructor(device, props) {
|
|
1656
|
+
super(device, props);
|
|
1657
|
+
this.device = device;
|
|
1658
|
+
let timestampWrites;
|
|
1659
|
+
if (device.features.has("timestamp-query")) {
|
|
1660
|
+
const webgpuQuerySet = props.timestampQuerySet;
|
|
1661
|
+
if (webgpuQuerySet) {
|
|
1662
|
+
timestampWrites = {
|
|
1663
|
+
querySet: webgpuQuerySet.handle,
|
|
1664
|
+
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
1665
|
+
endOfPassWriteIndex: props.endTimestampIndex
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
this.handle = this.props.handle || device.commandEncoder.handle.beginComputePass({
|
|
1670
|
+
label: this.props.id,
|
|
1671
|
+
timestampWrites
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
/** @note no WebGPU destroy method, just gc */
|
|
1675
|
+
destroy() {
|
|
1676
|
+
}
|
|
1677
|
+
end() {
|
|
1678
|
+
this.handle.end();
|
|
1679
|
+
}
|
|
1680
|
+
setPipeline(pipeline) {
|
|
1681
|
+
const wgpuPipeline = pipeline;
|
|
1682
|
+
this.handle.setPipeline(wgpuPipeline.handle);
|
|
1683
|
+
this._webgpuPipeline = wgpuPipeline;
|
|
1684
|
+
this.setBindings([]);
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* Sets an array of bindings (uniform buffers, samplers, textures, ...)
|
|
1688
|
+
* TODO - still some API confusion - does this method go here or on the pipeline?
|
|
1689
|
+
*/
|
|
1690
|
+
setBindings(bindings) {
|
|
1691
|
+
const bindGroup = this._webgpuPipeline._getBindGroup();
|
|
1692
|
+
this.handle.setBindGroup(0, bindGroup);
|
|
1693
|
+
}
|
|
1694
|
+
/**
|
|
1695
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1696
|
+
* @param x X dimension of the grid of work groups to dispatch.
|
|
1697
|
+
* @param y Y dimension of the grid of work groups to dispatch.
|
|
1698
|
+
* @param z Z dimension of the grid of work groups to dispatch.
|
|
1699
|
+
*/
|
|
1700
|
+
dispatch(x, y, z) {
|
|
1701
|
+
this.handle.dispatchWorkgroups(x, y, z);
|
|
1702
|
+
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Dispatch work to be performed with the current ComputePipeline.
|
|
1705
|
+
*
|
|
1706
|
+
* 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()
|
|
1707
|
+
* @param indirectBuffer
|
|
1708
|
+
* @param indirectOffset offset in buffer to the beginning of the dispatch data.
|
|
1709
|
+
*/
|
|
1710
|
+
dispatchIndirect(indirectBuffer, indirectByteOffset = 0) {
|
|
1711
|
+
const webgpuBuffer = indirectBuffer;
|
|
1712
|
+
this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
|
|
1713
|
+
}
|
|
1714
|
+
pushDebugGroup(groupLabel) {
|
|
1715
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1716
|
+
}
|
|
1717
|
+
popDebugGroup() {
|
|
1718
|
+
this.handle.popDebugGroup();
|
|
1719
|
+
}
|
|
1720
|
+
insertDebugMarker(markerLabel) {
|
|
1721
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1458
1724
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
// src/adapter/resources/webgpu-command-encoder.ts
|
|
1728
|
+
var import_core18, WebGPUCommandEncoder;
|
|
1729
|
+
var init_webgpu_command_encoder = __esm({
|
|
1730
|
+
"src/adapter/resources/webgpu-command-encoder.ts"() {
|
|
1731
|
+
"use strict";
|
|
1732
|
+
import_core18 = __toESM(require_core(), 1);
|
|
1733
|
+
init_webgpu_command_buffer();
|
|
1734
|
+
init_webgpu_render_pass();
|
|
1735
|
+
init_webgpu_compute_pass();
|
|
1736
|
+
WebGPUCommandEncoder = class extends import_core18.CommandEncoder {
|
|
1737
|
+
device;
|
|
1738
|
+
handle;
|
|
1739
|
+
constructor(device, props = {}) {
|
|
1740
|
+
super(device, props);
|
|
1741
|
+
this.device = device;
|
|
1742
|
+
this.handle = props.handle || this.device.handle.createCommandEncoder({
|
|
1743
|
+
label: this.props.id
|
|
1744
|
+
// TODO was this removed in standard?
|
|
1745
|
+
// measureExecutionTime: this.props.measureExecutionTime
|
|
1746
|
+
});
|
|
1747
|
+
this.handle.label = this.props.id;
|
|
1748
|
+
}
|
|
1749
|
+
destroy() {
|
|
1750
|
+
}
|
|
1751
|
+
finish(props) {
|
|
1752
|
+
this.device.pushErrorScope("validation");
|
|
1753
|
+
const commandBuffer = new WebGPUCommandBuffer(this, {
|
|
1754
|
+
id: props?.id || "unnamed-command-buffer"
|
|
1755
|
+
});
|
|
1756
|
+
this.device.popErrorScope((error) => {
|
|
1757
|
+
const message = `${this} command encoding: ${error.message}. Maybe add depthWriteEnabled to your Model?`;
|
|
1758
|
+
this.device.reportError(new Error(message), this)();
|
|
1759
|
+
this.device.debug();
|
|
1760
|
+
});
|
|
1761
|
+
return commandBuffer;
|
|
1762
|
+
}
|
|
1763
|
+
/**
|
|
1764
|
+
* Allows a render pass to begin against a canvas context
|
|
1765
|
+
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1766
|
+
*/
|
|
1767
|
+
beginRenderPass(props) {
|
|
1768
|
+
return new WebGPURenderPass(this.device, props);
|
|
1769
|
+
}
|
|
1770
|
+
beginComputePass(props) {
|
|
1771
|
+
return new WebGPUComputePass(this.device, props);
|
|
1772
|
+
}
|
|
1773
|
+
// beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
|
|
1774
|
+
// beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
|
|
1775
|
+
copyBufferToBuffer(options) {
|
|
1776
|
+
const webgpuSourceBuffer = options.sourceBuffer;
|
|
1777
|
+
const WebGPUDestinationBuffer = options.destinationBuffer;
|
|
1778
|
+
this.handle.copyBufferToBuffer(
|
|
1779
|
+
webgpuSourceBuffer.handle,
|
|
1780
|
+
options.sourceOffset ?? 0,
|
|
1781
|
+
WebGPUDestinationBuffer.handle,
|
|
1782
|
+
options.destinationOffset ?? 0,
|
|
1783
|
+
options.size ?? 0
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
copyBufferToTexture(options) {
|
|
1787
|
+
const webgpuSourceBuffer = options.sourceBuffer;
|
|
1788
|
+
const WebGPUDestinationTexture = options.destinationTexture;
|
|
1789
|
+
this.handle.copyBufferToTexture(
|
|
1790
|
+
{
|
|
1791
|
+
buffer: webgpuSourceBuffer.handle,
|
|
1792
|
+
offset: options.offset ?? 0,
|
|
1793
|
+
bytesPerRow: options.bytesPerRow,
|
|
1794
|
+
rowsPerImage: options.rowsPerImage
|
|
1795
|
+
},
|
|
1796
|
+
{
|
|
1797
|
+
texture: WebGPUDestinationTexture.handle,
|
|
1798
|
+
mipLevel: options.mipLevel ?? 0,
|
|
1799
|
+
origin: options.origin ?? {}
|
|
1800
|
+
// aspect: options.aspect
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
// @ts-ignore
|
|
1804
|
+
width: options.extent?.[0],
|
|
1805
|
+
height: options.extent?.[1],
|
|
1806
|
+
depthOrArrayLayers: options.extent?.[2]
|
|
1807
|
+
}
|
|
1808
|
+
);
|
|
1809
|
+
}
|
|
1810
|
+
copyTextureToBuffer(options) {
|
|
1811
|
+
}
|
|
1812
|
+
copyTextureToTexture(options) {
|
|
1813
|
+
}
|
|
1814
|
+
pushDebugGroup(groupLabel) {
|
|
1815
|
+
this.handle.pushDebugGroup(groupLabel);
|
|
1816
|
+
}
|
|
1817
|
+
popDebugGroup() {
|
|
1818
|
+
this.handle.popDebugGroup();
|
|
1819
|
+
}
|
|
1820
|
+
insertDebugMarker(markerLabel) {
|
|
1821
|
+
this.handle.insertDebugMarker(markerLabel);
|
|
1822
|
+
}
|
|
1823
|
+
resolveQuerySet(querySet, destination, options) {
|
|
1824
|
+
const webgpuQuerySet = querySet;
|
|
1825
|
+
const webgpuBuffer = destination;
|
|
1826
|
+
this.handle.resolveQuerySet(
|
|
1827
|
+
webgpuQuerySet.handle,
|
|
1828
|
+
options?.firstQuery || 0,
|
|
1829
|
+
options?.queryCount || querySet.props.count - (options?.firstQuery || 0),
|
|
1830
|
+
webgpuBuffer.handle,
|
|
1831
|
+
options?.destinationOffset || 0
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
};
|
|
1471
1835
|
}
|
|
1472
|
-
};
|
|
1836
|
+
});
|
|
1473
1837
|
|
|
1474
1838
|
// src/adapter/resources/webgpu-query-set.ts
|
|
1475
|
-
var
|
|
1476
|
-
var
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1839
|
+
var import_core19, WebGPUQuerySet;
|
|
1840
|
+
var init_webgpu_query_set = __esm({
|
|
1841
|
+
"src/adapter/resources/webgpu-query-set.ts"() {
|
|
1842
|
+
"use strict";
|
|
1843
|
+
import_core19 = __toESM(require_core(), 1);
|
|
1844
|
+
WebGPUQuerySet = class extends import_core19.QuerySet {
|
|
1845
|
+
device;
|
|
1846
|
+
handle;
|
|
1847
|
+
constructor(device, props) {
|
|
1848
|
+
super(device, props);
|
|
1849
|
+
this.device = device;
|
|
1850
|
+
this.handle = this.props.handle || this.device.handle.createQuerySet({
|
|
1851
|
+
type: this.props.type,
|
|
1852
|
+
count: this.props.count
|
|
1853
|
+
});
|
|
1854
|
+
this.handle.label = this.props.id;
|
|
1855
|
+
}
|
|
1856
|
+
destroy() {
|
|
1857
|
+
this.handle?.destroy();
|
|
1858
|
+
this.handle = null;
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1491
1861
|
}
|
|
1492
|
-
};
|
|
1862
|
+
});
|
|
1493
1863
|
|
|
1494
1864
|
// src/adapter/resources/webgpu-pipeline-layout.ts
|
|
1495
|
-
var
|
|
1496
|
-
var
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1865
|
+
var import_core20, WebGPUPipelineLayout, isStorageTextureBindingLayout;
|
|
1866
|
+
var init_webgpu_pipeline_layout = __esm({
|
|
1867
|
+
"src/adapter/resources/webgpu-pipeline-layout.ts"() {
|
|
1868
|
+
"use strict";
|
|
1869
|
+
import_core20 = __toESM(require_core(), 1);
|
|
1870
|
+
WebGPUPipelineLayout = class extends import_core20.PipelineLayout {
|
|
1871
|
+
device;
|
|
1872
|
+
handle;
|
|
1873
|
+
constructor(device, props) {
|
|
1874
|
+
super(device, props);
|
|
1875
|
+
this.device = device;
|
|
1876
|
+
const bindGroupEntries = this.mapShaderLayoutToBindGroupEntries();
|
|
1877
|
+
this.handle = this.device.handle.createPipelineLayout({
|
|
1878
|
+
label: props?.id ?? "unnamed-pipeline-layout",
|
|
1879
|
+
bindGroupLayouts: [
|
|
1880
|
+
// TODO (kaapp): We can cache these to re-use them across
|
|
1881
|
+
// layers, particularly if using a separate group for injected
|
|
1882
|
+
// bindings (e.g. project/lighting)
|
|
1883
|
+
this.device.handle.createBindGroupLayout({
|
|
1884
|
+
label: "bind-group-layout",
|
|
1885
|
+
entries: bindGroupEntries
|
|
1886
|
+
})
|
|
1887
|
+
]
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
destroy() {
|
|
1891
|
+
this.handle = null;
|
|
1892
|
+
}
|
|
1893
|
+
mapShaderLayoutToBindGroupEntries() {
|
|
1894
|
+
const bindGroupEntries = [];
|
|
1895
|
+
for (let i = 0; i < this.props.shaderLayout.bindings.length; i++) {
|
|
1896
|
+
const binding = this.props.shaderLayout.bindings[i];
|
|
1897
|
+
const bindingTypeInfo = {};
|
|
1898
|
+
switch (binding.type) {
|
|
1899
|
+
case "uniform": {
|
|
1900
|
+
bindingTypeInfo.buffer = {
|
|
1901
|
+
type: "uniform",
|
|
1902
|
+
hasDynamicOffset: binding.hasDynamicOffset,
|
|
1903
|
+
minBindingSize: binding.minBindingSize
|
|
1904
|
+
};
|
|
1905
|
+
break;
|
|
1906
|
+
}
|
|
1907
|
+
case "read-only-storage": {
|
|
1908
|
+
bindingTypeInfo.buffer = {
|
|
1909
|
+
type: "read-only-storage",
|
|
1910
|
+
hasDynamicOffset: binding.hasDynamicOffset,
|
|
1911
|
+
minBindingSize: binding.minBindingSize
|
|
1912
|
+
};
|
|
1913
|
+
break;
|
|
1914
|
+
}
|
|
1915
|
+
case "sampler": {
|
|
1916
|
+
bindingTypeInfo.sampler = {
|
|
1917
|
+
type: binding.samplerType
|
|
1918
|
+
};
|
|
1919
|
+
break;
|
|
1920
|
+
}
|
|
1921
|
+
case "storage": {
|
|
1922
|
+
if (isStorageTextureBindingLayout(binding)) {
|
|
1923
|
+
bindingTypeInfo.storageTexture = {
|
|
1924
|
+
// TODO (kaapp): Not all formats in the binding layout are supported
|
|
1925
|
+
// by WebGPU, but at least it will provide a clear error for now.
|
|
1926
|
+
format: binding.format,
|
|
1927
|
+
access: binding.access,
|
|
1928
|
+
viewDimension: binding.viewDimension
|
|
1929
|
+
};
|
|
1930
|
+
} else {
|
|
1931
|
+
bindingTypeInfo.buffer = {
|
|
1932
|
+
type: "storage",
|
|
1933
|
+
hasDynamicOffset: binding.hasDynamicOffset,
|
|
1934
|
+
minBindingSize: binding.minBindingSize
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
break;
|
|
1938
|
+
}
|
|
1939
|
+
case "texture": {
|
|
1940
|
+
bindingTypeInfo.texture = {
|
|
1941
|
+
multisampled: binding.multisampled,
|
|
1942
|
+
sampleType: binding.sampleType,
|
|
1943
|
+
viewDimension: binding.viewDimension
|
|
1944
|
+
};
|
|
1945
|
+
break;
|
|
1946
|
+
}
|
|
1947
|
+
default: {
|
|
1948
|
+
import_core20.log.warn("unhandled binding type when creating pipeline descriptor")();
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
const VISIBILITY_ALL = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
|
|
1952
|
+
bindGroupEntries.push({
|
|
1953
|
+
binding: binding.location,
|
|
1954
|
+
visibility: binding.visibility || VISIBILITY_ALL,
|
|
1955
|
+
...bindingTypeInfo
|
|
1956
|
+
});
|
|
1532
1957
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1958
|
+
return bindGroupEntries;
|
|
1959
|
+
}
|
|
1960
|
+
};
|
|
1961
|
+
isStorageTextureBindingLayout = (maybe) => {
|
|
1962
|
+
return maybe.format !== void 0;
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
|
|
1967
|
+
// src/adapter/webgpu-device.ts
|
|
1968
|
+
var webgpu_device_exports = {};
|
|
1969
|
+
__export(webgpu_device_exports, {
|
|
1970
|
+
WebGPUDevice: () => WebGPUDevice
|
|
1971
|
+
});
|
|
1972
|
+
var import_core21, WebGPUDevice;
|
|
1973
|
+
var init_webgpu_device = __esm({
|
|
1974
|
+
"src/adapter/webgpu-device.ts"() {
|
|
1975
|
+
"use strict";
|
|
1976
|
+
import_core21 = __toESM(require_core(), 1);
|
|
1977
|
+
init_webgpu_buffer();
|
|
1978
|
+
init_webgpu_texture();
|
|
1979
|
+
init_webgpu_external_texture();
|
|
1980
|
+
init_webgpu_sampler();
|
|
1981
|
+
init_webgpu_shader();
|
|
1982
|
+
init_webgpu_render_pipeline();
|
|
1983
|
+
init_webgpu_framebuffer();
|
|
1984
|
+
init_webgpu_compute_pipeline();
|
|
1985
|
+
init_webgpu_vertex_array();
|
|
1986
|
+
init_webgpu_canvas_context();
|
|
1987
|
+
init_webgpu_command_encoder();
|
|
1988
|
+
init_webgpu_query_set();
|
|
1989
|
+
init_webgpu_pipeline_layout();
|
|
1990
|
+
WebGPUDevice = class extends import_core21.Device {
|
|
1991
|
+
/** The underlying WebGPU device */
|
|
1992
|
+
handle;
|
|
1993
|
+
/* The underlying WebGPU adapter */
|
|
1994
|
+
adapter;
|
|
1995
|
+
/* The underlying WebGPU adapter's info */
|
|
1996
|
+
adapterInfo;
|
|
1997
|
+
/** type of this device */
|
|
1998
|
+
type = "webgpu";
|
|
1999
|
+
preferredColorFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
2000
|
+
preferredDepthFormat = "depth24plus";
|
|
2001
|
+
features;
|
|
2002
|
+
info;
|
|
2003
|
+
limits;
|
|
2004
|
+
lost;
|
|
2005
|
+
canvasContext = null;
|
|
2006
|
+
_isLost = false;
|
|
2007
|
+
commandEncoder;
|
|
2008
|
+
get [Symbol.toStringTag]() {
|
|
2009
|
+
return "WebGPUDevice";
|
|
2010
|
+
}
|
|
2011
|
+
toString() {
|
|
2012
|
+
return `WebGPUDevice(${this.id})`;
|
|
2013
|
+
}
|
|
2014
|
+
constructor(props, device, adapter, adapterInfo) {
|
|
2015
|
+
super({ ...props, id: props.id || "webgpu-device" });
|
|
2016
|
+
this.handle = device;
|
|
2017
|
+
this.adapter = adapter;
|
|
2018
|
+
this.adapterInfo = adapterInfo;
|
|
2019
|
+
this.info = this._getInfo();
|
|
2020
|
+
this.features = this._getFeatures();
|
|
2021
|
+
this.limits = this.handle.limits;
|
|
2022
|
+
device.addEventListener("uncapturederror", (event) => {
|
|
2023
|
+
event.preventDefault();
|
|
2024
|
+
const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown WebGPU error";
|
|
2025
|
+
this.reportError(new Error(errorMessage), this)();
|
|
2026
|
+
this.debug();
|
|
2027
|
+
});
|
|
2028
|
+
this.lost = new Promise(async (resolve) => {
|
|
2029
|
+
const lostInfo = await this.handle.lost;
|
|
2030
|
+
this._isLost = true;
|
|
2031
|
+
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
2032
|
+
});
|
|
2033
|
+
const canvasContextProps = import_core21.Device._getCanvasContextProps(props);
|
|
2034
|
+
if (canvasContextProps) {
|
|
2035
|
+
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
|
|
1540
2036
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
2037
|
+
this.commandEncoder = this.createCommandEncoder({});
|
|
2038
|
+
}
|
|
2039
|
+
// TODO
|
|
2040
|
+
// Load the glslang module now so that it is available synchronously when compiling shaders
|
|
2041
|
+
// const {glsl = true} = props;
|
|
2042
|
+
// this.glslang = glsl && await loadGlslangModule();
|
|
2043
|
+
destroy() {
|
|
2044
|
+
this.handle.destroy();
|
|
2045
|
+
}
|
|
2046
|
+
get isLost() {
|
|
2047
|
+
return this._isLost;
|
|
2048
|
+
}
|
|
2049
|
+
isVertexFormatSupported(format) {
|
|
2050
|
+
const info = this.getVertexFormatInfo(format);
|
|
2051
|
+
return !info.webglOnly;
|
|
2052
|
+
}
|
|
2053
|
+
getTextureByteAlignment() {
|
|
2054
|
+
return 1;
|
|
2055
|
+
}
|
|
2056
|
+
createBuffer(props) {
|
|
2057
|
+
const newProps = this._normalizeBufferProps(props);
|
|
2058
|
+
return new WebGPUBuffer(this, newProps);
|
|
2059
|
+
}
|
|
2060
|
+
createTexture(props) {
|
|
2061
|
+
return new WebGPUTexture(this, props);
|
|
2062
|
+
}
|
|
2063
|
+
createExternalTexture(props) {
|
|
2064
|
+
return new WebGPUExternalTexture(this, props);
|
|
2065
|
+
}
|
|
2066
|
+
createShader(props) {
|
|
2067
|
+
return new WebGPUShader(this, props);
|
|
2068
|
+
}
|
|
2069
|
+
createSampler(props) {
|
|
2070
|
+
return new WebGPUSampler(this, props);
|
|
2071
|
+
}
|
|
2072
|
+
createRenderPipeline(props) {
|
|
2073
|
+
return new WebGPURenderPipeline(this, props);
|
|
2074
|
+
}
|
|
2075
|
+
createFramebuffer(props) {
|
|
2076
|
+
return new WebGPUFramebuffer(this, props);
|
|
2077
|
+
}
|
|
2078
|
+
createComputePipeline(props) {
|
|
2079
|
+
return new WebGPUComputePipeline(this, props);
|
|
2080
|
+
}
|
|
2081
|
+
createVertexArray(props) {
|
|
2082
|
+
return new WebGPUVertexArray(this, props);
|
|
2083
|
+
}
|
|
2084
|
+
createCommandEncoder(props) {
|
|
2085
|
+
return new WebGPUCommandEncoder(this, props);
|
|
2086
|
+
}
|
|
2087
|
+
// WebGPU specifics
|
|
2088
|
+
createTransformFeedback(props) {
|
|
2089
|
+
throw new Error("Transform feedback not supported in WebGPU");
|
|
2090
|
+
}
|
|
2091
|
+
createQuerySet(props) {
|
|
2092
|
+
return new WebGPUQuerySet(this, props);
|
|
2093
|
+
}
|
|
2094
|
+
createCanvasContext(props) {
|
|
2095
|
+
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
2096
|
+
}
|
|
2097
|
+
createPipelineLayout(props) {
|
|
2098
|
+
return new WebGPUPipelineLayout(this, props);
|
|
2099
|
+
}
|
|
2100
|
+
submit(commandBuffer) {
|
|
2101
|
+
if (!commandBuffer) {
|
|
2102
|
+
commandBuffer = this.commandEncoder.finish();
|
|
2103
|
+
this.commandEncoder.destroy();
|
|
2104
|
+
this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
|
|
1546
2105
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
2106
|
+
this.pushErrorScope("validation");
|
|
2107
|
+
this.handle.queue.submit([commandBuffer.handle]);
|
|
2108
|
+
this.popErrorScope((error) => {
|
|
2109
|
+
this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
|
|
2110
|
+
this.debug();
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
// WebGPU specific
|
|
2114
|
+
pushErrorScope(scope) {
|
|
2115
|
+
this.handle.pushErrorScope(scope);
|
|
2116
|
+
}
|
|
2117
|
+
popErrorScope(handler) {
|
|
2118
|
+
this.handle.popErrorScope().then((error) => {
|
|
2119
|
+
if (error) {
|
|
2120
|
+
handler(error);
|
|
1562
2121
|
}
|
|
1563
|
-
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
// PRIVATE METHODS
|
|
2125
|
+
_getInfo() {
|
|
2126
|
+
const [driver, driverVersion] = (this.adapterInfo.driver || "").split(" Version ");
|
|
2127
|
+
const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
|
|
2128
|
+
const renderer = driver || "";
|
|
2129
|
+
const version = driverVersion || "";
|
|
2130
|
+
const gpu = vendor === "apple" ? "apple" : "unknown";
|
|
2131
|
+
const gpuArchitecture = this.adapterInfo.architecture || "unknown";
|
|
2132
|
+
const gpuBackend = this.adapterInfo.backend || "unknown";
|
|
2133
|
+
const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
|
|
2134
|
+
return {
|
|
2135
|
+
type: "webgpu",
|
|
2136
|
+
vendor,
|
|
2137
|
+
renderer,
|
|
2138
|
+
version,
|
|
2139
|
+
gpu,
|
|
2140
|
+
gpuType,
|
|
2141
|
+
gpuBackend,
|
|
2142
|
+
gpuArchitecture,
|
|
2143
|
+
shadingLanguage: "wgsl",
|
|
2144
|
+
shadingLanguageVersion: 100
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
_getFeatures() {
|
|
2148
|
+
const features = new Set(this.handle.features);
|
|
2149
|
+
if (features.has("depth-clamping")) {
|
|
2150
|
+
features.delete("depth-clamping");
|
|
2151
|
+
features.add("depth-clip-control");
|
|
1564
2152
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
multisampled: binding.multisampled,
|
|
1568
|
-
sampleType: binding.sampleType,
|
|
1569
|
-
viewDimension: binding.viewDimension
|
|
1570
|
-
};
|
|
1571
|
-
break;
|
|
2153
|
+
if (features.has("texture-compression-bc")) {
|
|
2154
|
+
features.add("texture-compression-bc5-webgl");
|
|
1572
2155
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
2156
|
+
const WEBGPU_ALWAYS_FEATURES = [
|
|
2157
|
+
"timer-query-webgl",
|
|
2158
|
+
"compilation-status-async-webgl",
|
|
2159
|
+
"float32-renderable-webgl",
|
|
2160
|
+
"float16-renderable-webgl",
|
|
2161
|
+
"norm16-renderable-webgl",
|
|
2162
|
+
"texture-filterable-anisotropic-webgl",
|
|
2163
|
+
"shader-noperspective-interpolation-webgl"
|
|
2164
|
+
];
|
|
2165
|
+
for (const feature of WEBGPU_ALWAYS_FEATURES) {
|
|
2166
|
+
features.add(feature);
|
|
1575
2167
|
}
|
|
2168
|
+
return new import_core21.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
|
|
1576
2169
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
...bindingTypeInfo
|
|
1582
|
-
});
|
|
1583
|
-
}
|
|
1584
|
-
return bindGroupEntries;
|
|
1585
|
-
}
|
|
1586
|
-
};
|
|
1587
|
-
var isStorageTextureBindingLayout = (maybe) => {
|
|
1588
|
-
return maybe.format !== void 0;
|
|
1589
|
-
};
|
|
1590
|
-
|
|
1591
|
-
// src/adapter/webgpu-device.ts
|
|
1592
|
-
var WebGPUDevice = class extends import_core19.Device {
|
|
1593
|
-
/** type of this device */
|
|
1594
|
-
type = "webgpu";
|
|
1595
|
-
/** The underlying WebGPU device */
|
|
1596
|
-
handle;
|
|
1597
|
-
/* The underlying WebGPU adapter */
|
|
1598
|
-
adapter;
|
|
1599
|
-
/* The underlying WebGPU adapter's info */
|
|
1600
|
-
adapterInfo;
|
|
1601
|
-
features;
|
|
1602
|
-
info;
|
|
1603
|
-
limits;
|
|
1604
|
-
lost;
|
|
1605
|
-
canvasContext = null;
|
|
1606
|
-
_isLost = false;
|
|
1607
|
-
commandEncoder = null;
|
|
1608
|
-
renderPass = null;
|
|
1609
|
-
constructor(props, device, adapter, adapterInfo) {
|
|
1610
|
-
super({ ...props, id: props.id || "webgpu-device" });
|
|
1611
|
-
this.handle = device;
|
|
1612
|
-
this.adapter = adapter;
|
|
1613
|
-
this.adapterInfo = adapterInfo;
|
|
1614
|
-
this.info = this._getInfo();
|
|
1615
|
-
this.features = this._getFeatures();
|
|
1616
|
-
this.limits = this.handle.limits;
|
|
1617
|
-
device.addEventListener("uncapturederror", (event) => {
|
|
1618
|
-
const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown WebGPU error";
|
|
1619
|
-
this.reportError(new Error(errorMessage));
|
|
1620
|
-
if (this.props.debug) {
|
|
1621
|
-
debugger;
|
|
1622
|
-
}
|
|
1623
|
-
event.preventDefault();
|
|
1624
|
-
});
|
|
1625
|
-
this.lost = new Promise(async (resolve) => {
|
|
1626
|
-
const lostInfo = await this.handle.lost;
|
|
1627
|
-
this._isLost = true;
|
|
1628
|
-
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
1629
|
-
});
|
|
1630
|
-
const canvasContextProps = import_core19.Device._getCanvasContextProps(props);
|
|
1631
|
-
if (canvasContextProps) {
|
|
1632
|
-
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
// TODO
|
|
1636
|
-
// Load the glslang module now so that it is available synchronously when compiling shaders
|
|
1637
|
-
// const {glsl = true} = props;
|
|
1638
|
-
// this.glslang = glsl && await loadGlslangModule();
|
|
1639
|
-
destroy() {
|
|
1640
|
-
this.handle.destroy();
|
|
1641
|
-
}
|
|
1642
|
-
get isLost() {
|
|
1643
|
-
return this._isLost;
|
|
1644
|
-
}
|
|
1645
|
-
createBuffer(props) {
|
|
1646
|
-
const newProps = this._normalizeBufferProps(props);
|
|
1647
|
-
return new WebGPUBuffer(this, newProps);
|
|
1648
|
-
}
|
|
1649
|
-
createTexture(props) {
|
|
1650
|
-
return new WebGPUTexture(this, props);
|
|
1651
|
-
}
|
|
1652
|
-
createExternalTexture(props) {
|
|
1653
|
-
return new WebGPUExternalTexture(this, props);
|
|
1654
|
-
}
|
|
1655
|
-
createShader(props) {
|
|
1656
|
-
return new WebGPUShader(this, props);
|
|
1657
|
-
}
|
|
1658
|
-
createSampler(props) {
|
|
1659
|
-
return new WebGPUSampler(this, props);
|
|
1660
|
-
}
|
|
1661
|
-
createRenderPipeline(props) {
|
|
1662
|
-
return new WebGPURenderPipeline(this, props);
|
|
1663
|
-
}
|
|
1664
|
-
createFramebuffer(props) {
|
|
1665
|
-
return new WebGPUFramebuffer(this, props);
|
|
1666
|
-
}
|
|
1667
|
-
createComputePipeline(props) {
|
|
1668
|
-
return new WebGPUComputePipeline(this, props);
|
|
1669
|
-
}
|
|
1670
|
-
createVertexArray(props) {
|
|
1671
|
-
return new WebGPUVertexArray(this, props);
|
|
1672
|
-
}
|
|
1673
|
-
// WebGPU specifics
|
|
1674
|
-
/**
|
|
1675
|
-
* Allows a render pass to begin against a canvas context
|
|
1676
|
-
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1677
|
-
*/
|
|
1678
|
-
beginRenderPass(props) {
|
|
1679
|
-
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1680
|
-
return new WebGPURenderPass(this, props);
|
|
1681
|
-
}
|
|
1682
|
-
beginComputePass(props) {
|
|
1683
|
-
this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
|
|
1684
|
-
return new WebGPUComputePass(this, props);
|
|
1685
|
-
}
|
|
1686
|
-
// createCommandEncoder(props: CommandEncoderProps): WebGPUCommandEncoder {
|
|
1687
|
-
// return new WebGPUCommandEncoder(this, props);
|
|
1688
|
-
// }
|
|
1689
|
-
createTransformFeedback(props) {
|
|
1690
|
-
throw new Error("Transform feedback not supported in WebGPU");
|
|
1691
|
-
}
|
|
1692
|
-
createQuerySet(props) {
|
|
1693
|
-
return new WebGPUQuerySet(this, props);
|
|
1694
|
-
}
|
|
1695
|
-
createCanvasContext(props) {
|
|
1696
|
-
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
1697
|
-
}
|
|
1698
|
-
createPipelineLayout(props) {
|
|
1699
|
-
return new WebGPUPipelineLayout(this, props);
|
|
1700
|
-
}
|
|
1701
|
-
submit() {
|
|
1702
|
-
const commandBuffer = this.commandEncoder?.finish();
|
|
1703
|
-
if (commandBuffer) {
|
|
1704
|
-
this.handle.pushErrorScope("validation");
|
|
1705
|
-
this.handle.queue.submit([commandBuffer]);
|
|
1706
|
-
this.handle.popErrorScope().then((error) => {
|
|
1707
|
-
if (error) {
|
|
1708
|
-
this.reportError(new Error(`WebGPU command submission failed: ${error.message}`));
|
|
2170
|
+
_getDeviceSpecificTextureFormatCapabilities(capabilities) {
|
|
2171
|
+
const { format } = capabilities;
|
|
2172
|
+
if (format.includes("webgl")) {
|
|
2173
|
+
return { format, create: false, render: false, filter: false, blend: false, store: false };
|
|
1709
2174
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
}
|
|
1713
|
-
// PRIVATE METHODS
|
|
1714
|
-
_getInfo() {
|
|
1715
|
-
const [driver, driverVersion] = (this.adapterInfo.driver || "").split(" Version ");
|
|
1716
|
-
const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
|
|
1717
|
-
const renderer = driver || "";
|
|
1718
|
-
const version = driverVersion || "";
|
|
1719
|
-
const gpu = vendor === "apple" ? "apple" : "unknown";
|
|
1720
|
-
const gpuArchitecture = this.adapterInfo.architecture || "unknown";
|
|
1721
|
-
const gpuBackend = this.adapterInfo.backend || "unknown";
|
|
1722
|
-
const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
|
|
1723
|
-
return {
|
|
1724
|
-
type: "webgpu",
|
|
1725
|
-
vendor,
|
|
1726
|
-
renderer,
|
|
1727
|
-
version,
|
|
1728
|
-
gpu,
|
|
1729
|
-
gpuType,
|
|
1730
|
-
gpuBackend,
|
|
1731
|
-
gpuArchitecture,
|
|
1732
|
-
shadingLanguage: "wgsl",
|
|
1733
|
-
shadingLanguageVersion: 100
|
|
2175
|
+
return capabilities;
|
|
2176
|
+
}
|
|
1734
2177
|
};
|
|
1735
2178
|
}
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
"float16-renderable-webgl",
|
|
1750
|
-
"norm16-renderable-webgl",
|
|
1751
|
-
"texture-filterable-anisotropic-webgl",
|
|
1752
|
-
"shader-noperspective-interpolation-webgl"
|
|
1753
|
-
];
|
|
1754
|
-
for (const feature of WEBGPU_ALWAYS_FEATURES) {
|
|
1755
|
-
features.add(feature);
|
|
1756
|
-
}
|
|
1757
|
-
return new import_core19.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
|
|
1758
|
-
}
|
|
1759
|
-
_getDeviceSpecificTextureFormatCapabilities(capabilities) {
|
|
1760
|
-
const { format } = capabilities;
|
|
1761
|
-
if (format.includes("webgl")) {
|
|
1762
|
-
return { format, create: false, render: false, filter: false, blend: false, store: false };
|
|
1763
|
-
}
|
|
1764
|
-
return capabilities;
|
|
1765
|
-
}
|
|
1766
|
-
// DEPRECATED METHODS
|
|
1767
|
-
// @deprecated
|
|
1768
|
-
copyExternalImageToTexture(options) {
|
|
1769
|
-
const {
|
|
1770
|
-
source,
|
|
1771
|
-
sourceX = 0,
|
|
1772
|
-
sourceY = 0,
|
|
1773
|
-
texture,
|
|
1774
|
-
mipLevel = 0,
|
|
1775
|
-
aspect = "all",
|
|
1776
|
-
colorSpace = "display-p3",
|
|
1777
|
-
premultipliedAlpha = false,
|
|
1778
|
-
// destinationX,
|
|
1779
|
-
// destinationY,
|
|
1780
|
-
// desitnationZ,
|
|
1781
|
-
width = texture.width,
|
|
1782
|
-
height = texture.height,
|
|
1783
|
-
depth = 1
|
|
1784
|
-
} = options;
|
|
1785
|
-
const webGpuTexture = texture;
|
|
1786
|
-
this.handle?.queue.copyExternalImageToTexture(
|
|
1787
|
-
// source: GPUImageCopyExternalImage
|
|
1788
|
-
{
|
|
1789
|
-
source,
|
|
1790
|
-
origin: [sourceX, sourceY]
|
|
1791
|
-
},
|
|
1792
|
-
// destination: GPUImageCopyTextureTagged
|
|
1793
|
-
{
|
|
1794
|
-
texture: webGpuTexture.handle,
|
|
1795
|
-
origin: [0, 0, 0],
|
|
1796
|
-
// [x, y, z],
|
|
1797
|
-
mipLevel,
|
|
1798
|
-
aspect,
|
|
1799
|
-
colorSpace,
|
|
1800
|
-
premultipliedAlpha
|
|
1801
|
-
},
|
|
1802
|
-
// copySize: GPUExtent3D
|
|
1803
|
-
[width, height, depth]
|
|
1804
|
-
);
|
|
1805
|
-
}
|
|
1806
|
-
};
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2181
|
+
// bundle.ts
|
|
2182
|
+
var bundle_exports = {};
|
|
2183
|
+
__export(bundle_exports, {
|
|
2184
|
+
WebGPUBuffer: () => WebGPUBuffer,
|
|
2185
|
+
WebGPUDevice: () => WebGPUDevice,
|
|
2186
|
+
WebGPUSampler: () => WebGPUSampler,
|
|
2187
|
+
WebGPUShader: () => WebGPUShader,
|
|
2188
|
+
WebGPUTexture: () => WebGPUTexture,
|
|
2189
|
+
webgpuAdapter: () => webgpuAdapter
|
|
2190
|
+
});
|
|
2191
|
+
__reExport(bundle_exports, __toESM(require_core(), 1));
|
|
1807
2192
|
|
|
1808
2193
|
// src/adapter/webgpu-adapter.ts
|
|
1809
|
-
var
|
|
2194
|
+
var import_core22 = __toESM(require_core(), 1);
|
|
2195
|
+
var WebGPUAdapter = class extends import_core22.Adapter {
|
|
1810
2196
|
/** type of device's created by this adapter */
|
|
1811
2197
|
type = "webgpu";
|
|
1812
|
-
constructor() {
|
|
1813
|
-
super();
|
|
1814
|
-
WebGPUDevice.adapter = this;
|
|
1815
|
-
}
|
|
1816
|
-
/** Check if WebGPU is available */
|
|
1817
2198
|
isSupported() {
|
|
1818
2199
|
return Boolean(typeof navigator !== "undefined" && navigator.gpu);
|
|
1819
2200
|
}
|
|
2201
|
+
isDeviceHandle(handle) {
|
|
2202
|
+
if (typeof GPUDevice !== "undefined" && handle instanceof GPUDevice) {
|
|
2203
|
+
return true;
|
|
2204
|
+
}
|
|
2205
|
+
if (handle?.queue) {
|
|
2206
|
+
return true;
|
|
2207
|
+
}
|
|
2208
|
+
return false;
|
|
2209
|
+
}
|
|
1820
2210
|
async create(props) {
|
|
1821
2211
|
if (!navigator.gpu) {
|
|
1822
|
-
throw new Error(
|
|
1823
|
-
"WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu"
|
|
1824
|
-
);
|
|
1825
|
-
}
|
|
1826
|
-
import_core20.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
1827
|
-
const adapter = await navigator.gpu.requestAdapter({
|
|
1828
|
-
powerPreference: "high-performance"
|
|
1829
|
-
// forceSoftware: false
|
|
1830
|
-
});
|
|
1831
|
-
if (!adapter) {
|
|
1832
|
-
throw new Error("Failed to request WebGPU adapter");
|
|
2212
|
+
throw new Error("WebGPU not available. Recent Chrome browsers should work.");
|
|
1833
2213
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
2214
|
+
import_core22.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
2215
|
+
try {
|
|
2216
|
+
const adapter = await navigator.gpu.requestAdapter({
|
|
2217
|
+
powerPreference: "high-performance"
|
|
2218
|
+
// forceSoftware: false
|
|
2219
|
+
});
|
|
2220
|
+
if (!adapter) {
|
|
2221
|
+
throw new Error("Failed to request WebGPU adapter");
|
|
2222
|
+
}
|
|
2223
|
+
const adapterInfo = adapter.info || // @ts-ignore
|
|
2224
|
+
await adapter.requestAdapterInfo?.();
|
|
2225
|
+
import_core22.log.probe(2, "Adapter available", adapterInfo)();
|
|
2226
|
+
const requiredFeatures = [];
|
|
2227
|
+
const requiredLimits = {};
|
|
2228
|
+
if (props._requestMaxLimits) {
|
|
2229
|
+
requiredFeatures.push(...Array.from(adapter.features));
|
|
2230
|
+
const limits = Object.keys(adapter.limits).filter(
|
|
2231
|
+
(key) => !["minSubgroupSize", "maxSubgroupSize"].includes(key)
|
|
2232
|
+
);
|
|
2233
|
+
for (const key of limits) {
|
|
2234
|
+
const limit = key;
|
|
2235
|
+
const value = adapter.limits[limit];
|
|
2236
|
+
if (typeof value === "number") {
|
|
2237
|
+
requiredLimits[limit] = value;
|
|
2238
|
+
}
|
|
1849
2239
|
}
|
|
1850
2240
|
}
|
|
2241
|
+
const gpuDevice = await adapter.requestDevice({
|
|
2242
|
+
requiredFeatures,
|
|
2243
|
+
requiredLimits
|
|
2244
|
+
});
|
|
2245
|
+
import_core22.log.probe(1, "GPUDevice available")();
|
|
2246
|
+
const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
|
|
2247
|
+
const device = new WebGPUDevice2(props, gpuDevice, adapter, adapterInfo);
|
|
2248
|
+
import_core22.log.probe(
|
|
2249
|
+
1,
|
|
2250
|
+
"Device created. For more info, set chrome://flags/#enable-webgpu-developer-features"
|
|
2251
|
+
)();
|
|
2252
|
+
import_core22.log.table(1, device.info)();
|
|
2253
|
+
return device;
|
|
2254
|
+
} finally {
|
|
2255
|
+
import_core22.log.groupEnd(1)();
|
|
1851
2256
|
}
|
|
1852
|
-
const gpuDevice = await adapter.requestDevice({
|
|
1853
|
-
requiredFeatures,
|
|
1854
|
-
requiredLimits
|
|
1855
|
-
});
|
|
1856
|
-
import_core20.log.probe(1, "GPUDevice available")();
|
|
1857
|
-
const device = new WebGPUDevice(props, gpuDevice, adapter, adapterInfo);
|
|
1858
|
-
import_core20.log.probe(
|
|
1859
|
-
1,
|
|
1860
|
-
"Device created. For more info, set chrome://flags/#enable-webgpu-developer-features"
|
|
1861
|
-
)();
|
|
1862
|
-
import_core20.log.table(1, device.info)();
|
|
1863
|
-
import_core20.log.groupEnd(1)();
|
|
1864
|
-
return device;
|
|
1865
2257
|
}
|
|
1866
2258
|
async attach(handle) {
|
|
1867
2259
|
throw new Error("WebGPUAdapter.attach() not implemented");
|
|
1868
2260
|
}
|
|
1869
2261
|
};
|
|
1870
2262
|
var webgpuAdapter = new WebGPUAdapter();
|
|
2263
|
+
|
|
2264
|
+
// src/index.ts
|
|
2265
|
+
init_webgpu_device();
|
|
2266
|
+
init_webgpu_buffer();
|
|
2267
|
+
init_webgpu_texture();
|
|
2268
|
+
init_webgpu_sampler();
|
|
2269
|
+
init_webgpu_shader();
|
|
1871
2270
|
return __toCommonJS(bundle_exports);
|
|
1872
2271
|
})();
|
|
1873
2272
|
return __exports__;
|