@luma.gl/webgpu 9.0.0-alpha.2 → 9.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/LICENSE +32 -0
  2. package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
  3. package/dist/adapter/helpers/convert-texture-format.d.ts +1 -1
  4. package/dist/adapter/helpers/convert-texture-format.js +0 -1
  5. package/dist/adapter/helpers/convert-texture-format.js.map +1 -1
  6. package/dist/adapter/helpers/generate-mipmaps.d.ts +1 -1
  7. package/dist/adapter/helpers/generate-mipmaps.js +1 -8
  8. package/dist/adapter/helpers/generate-mipmaps.js.map +1 -1
  9. package/dist/adapter/helpers/get-bind-group.d.ts +1 -1
  10. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  11. package/dist/adapter/helpers/get-bind-group.js +0 -9
  12. package/dist/adapter/helpers/get-bind-group.js.map +1 -1
  13. package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +1 -1
  14. package/dist/adapter/helpers/get-vertex-buffer-layout.js +3 -17
  15. package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
  16. package/dist/adapter/helpers/webgpu-parameters.d.ts +1 -1
  17. package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
  18. package/dist/adapter/helpers/webgpu-parameters.js +50 -47
  19. package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
  20. package/dist/adapter/resources/webgpu-buffer.d.ts +3 -4
  21. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  22. package/dist/adapter/resources/webgpu-buffer.js +12 -26
  23. package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
  24. package/dist/adapter/resources/webgpu-command-encoder.d.ts +3 -4
  25. package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
  26. package/dist/adapter/resources/webgpu-command-encoder.js +7 -24
  27. package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
  28. package/dist/adapter/resources/webgpu-compute-pass.d.ts +5 -5
  29. package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
  30. package/dist/adapter/resources/webgpu-compute-pass.js +11 -23
  31. package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
  32. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +3 -3
  33. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
  34. package/dist/adapter/resources/webgpu-compute-pipeline.js +3 -7
  35. package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
  36. package/dist/adapter/resources/webgpu-external-texture.d.ts +4 -4
  37. package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
  38. package/dist/adapter/resources/webgpu-external-texture.js +2 -9
  39. package/dist/adapter/resources/webgpu-external-texture.js.map +1 -1
  40. package/dist/adapter/resources/webgpu-framebuffer.d.ts +5 -5
  41. package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
  42. package/dist/adapter/resources/webgpu-framebuffer.js +12 -30
  43. package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
  44. package/dist/adapter/resources/webgpu-query.js.map +1 -1
  45. package/dist/adapter/resources/webgpu-render-pass.d.ts +5 -5
  46. package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
  47. package/dist/adapter/resources/webgpu-render-pass.js +17 -30
  48. package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
  49. package/dist/adapter/resources/webgpu-render-pipeline.d.ts +7 -4
  50. package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
  51. package/dist/adapter/resources/webgpu-render-pipeline.js +25 -43
  52. package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
  53. package/dist/adapter/resources/webgpu-sampler.d.ts +3 -3
  54. package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
  55. package/dist/adapter/resources/webgpu-sampler.js +8 -7
  56. package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
  57. package/dist/adapter/resources/webgpu-shader.d.ts +4 -4
  58. package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
  59. package/dist/adapter/resources/webgpu-shader.js +2 -16
  60. package/dist/adapter/resources/webgpu-shader.js.map +1 -1
  61. package/dist/adapter/resources/webgpu-texture.d.ts +4 -4
  62. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  63. package/dist/adapter/resources/webgpu-texture.js +4 -20
  64. package/dist/adapter/resources/webgpu-texture.js.map +1 -1
  65. package/dist/adapter/webgpu-canvas-context.d.ts +5 -7
  66. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  67. package/dist/adapter/webgpu-canvas-context.js +10 -31
  68. package/dist/adapter/webgpu-canvas-context.js.map +1 -1
  69. package/dist/adapter/webgpu-device.d.ts +19 -19
  70. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  71. package/dist/adapter/webgpu-device.js +42 -71
  72. package/dist/adapter/webgpu-device.js.map +1 -1
  73. package/dist/adapter/webgpu-types.js.map +1 -1
  74. package/dist/dist.dev.js +3060 -0
  75. package/dist/glsl/glsllang.js +0 -1
  76. package/dist/glsl/glsllang.js.map +1 -1
  77. package/dist/index.cjs +1442 -0
  78. package/dist/index.d.ts +5 -7
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +5 -7
  81. package/dist/index.js.map +1 -1
  82. package/dist.min.js +17 -0
  83. package/package.json +18 -9
  84. package/src/.DS_Store +0 -0
  85. package/src/adapter/.DS_Store +0 -0
  86. package/src/adapter/helpers/generate-mipmaps.ts +1 -1
  87. package/src/adapter/helpers/get-bind-group.ts +4 -4
  88. package/src/adapter/helpers/get-vertex-buffer-layout.ts +3 -3
  89. package/src/adapter/helpers/webgpu-parameters.ts +55 -46
  90. package/src/adapter/resources/webgpu-buffer.ts +6 -10
  91. package/src/adapter/resources/webgpu-command-encoder.ts +22 -20
  92. package/src/adapter/resources/webgpu-compute-pass.ts +12 -12
  93. package/src/adapter/resources/webgpu-compute-pipeline.ts +5 -4
  94. package/src/adapter/resources/webgpu-external-texture.ts +4 -4
  95. package/src/adapter/resources/webgpu-framebuffer.ts +18 -18
  96. package/src/adapter/resources/webgpu-query.ts +2 -2
  97. package/src/adapter/resources/webgpu-render-pass.ts +15 -12
  98. package/src/adapter/resources/webgpu-render-pipeline.ts +32 -15
  99. package/src/adapter/resources/webgpu-sampler.ts +11 -4
  100. package/src/adapter/resources/webgpu-shader.ts +7 -5
  101. package/src/adapter/resources/webgpu-texture.ts +7 -6
  102. package/src/adapter/webgpu-canvas-context.ts +16 -12
  103. package/src/adapter/webgpu-device.ts +63 -50
  104. package/src/index.ts +6 -9
  105. package/dist/bundle.d.ts +0 -2
  106. package/dist/bundle.d.ts.map +0 -1
  107. package/dist/bundle.js +0 -5
  108. package/dist/bundle.js.map +0 -1
  109. package/dist/init.d.ts +0 -2
  110. package/dist/init.d.ts.map +0 -1
  111. package/dist/init.js +0 -4
  112. package/dist/init.js.map +0 -1
  113. package/src/bundle.ts +0 -4
  114. package/src/init.ts +0 -4
@@ -0,0 +1,3060 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if (typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory();
4
+ else if (typeof define === 'function' && define.amd) define([], factory);
5
+ else if (typeof exports === 'object') exports['luma'] = factory();
6
+ else root['luma'] = factory();})(globalThis, function () {
7
+ var __exports__ = (() => {
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __export = (target, all) => {
14
+ for (var name in all)
15
+ __defProp(target, name, { get: all[name], enumerable: true });
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") {
19
+ for (let key of __getOwnPropNames(from))
20
+ if (!__hasOwnProp.call(to, key) && key !== except)
21
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
+ }
23
+ return to;
24
+ };
25
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
+ var __publicField = (obj, key, value) => {
27
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
28
+ return value;
29
+ };
30
+
31
+ // src/index.ts
32
+ var src_exports = {};
33
+ __export(src_exports, {
34
+ WebGPUBuffer: () => WebGPUBuffer,
35
+ WebGPUDevice: () => WebGPUDevice,
36
+ WebGPUSampler: () => WebGPUSampler,
37
+ WebGPUShader: () => WebGPUShader,
38
+ WebGPUTexture: () => WebGPUTexture
39
+ });
40
+
41
+ // ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
42
+ function isElectron(mockUserAgent) {
43
+ if (typeof window !== "undefined" && typeof window.process === "object" && window.process.type === "renderer") {
44
+ return true;
45
+ }
46
+ if (typeof process !== "undefined" && typeof process.versions === "object" && Boolean(process.versions["electron"])) {
47
+ return true;
48
+ }
49
+ const realUserAgent = typeof navigator === "object" && typeof navigator.userAgent === "string" && navigator.userAgent;
50
+ const userAgent = mockUserAgent || realUserAgent;
51
+ if (userAgent && userAgent.indexOf("Electron") >= 0) {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+
57
+ // ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
58
+ function isBrowser() {
59
+ const isNode = typeof process === "object" && String(process) === "[object process]" && !process.browser;
60
+ return !isNode || isElectron();
61
+ }
62
+
63
+ // ../../node_modules/@probe.gl/env/dist/lib/globals.js
64
+ var self_ = globalThis.self || globalThis.window || globalThis.global;
65
+ var window_ = globalThis.window || globalThis.self || globalThis.global;
66
+ var document_ = globalThis.document || {};
67
+ var process_ = globalThis.process || {};
68
+ var console_ = globalThis.console;
69
+ var navigator_ = globalThis.navigator || {};
70
+
71
+ // ../../node_modules/@probe.gl/env/dist/utils/globals.js
72
+ var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "untranspiled source";
73
+ var isBrowser2 = isBrowser();
74
+
75
+ // ../../node_modules/@babel/runtime/helpers/esm/typeof.js
76
+ function _typeof(obj) {
77
+ "@babel/helpers - typeof";
78
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj2) {
79
+ return typeof obj2;
80
+ } : function(obj2) {
81
+ return obj2 && "function" == typeof Symbol && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
82
+ }, _typeof(obj);
83
+ }
84
+
85
+ // ../../node_modules/@babel/runtime/helpers/esm/toPrimitive.js
86
+ function _toPrimitive(input, hint) {
87
+ if (_typeof(input) !== "object" || input === null)
88
+ return input;
89
+ var prim = input[Symbol.toPrimitive];
90
+ if (prim !== void 0) {
91
+ var res = prim.call(input, hint || "default");
92
+ if (_typeof(res) !== "object")
93
+ return res;
94
+ throw new TypeError("@@toPrimitive must return a primitive value.");
95
+ }
96
+ return (hint === "string" ? String : Number)(input);
97
+ }
98
+
99
+ // ../../node_modules/@babel/runtime/helpers/esm/toPropertyKey.js
100
+ function _toPropertyKey(arg) {
101
+ var key = _toPrimitive(arg, "string");
102
+ return _typeof(key) === "symbol" ? key : String(key);
103
+ }
104
+
105
+ // ../../node_modules/@babel/runtime/helpers/esm/defineProperty.js
106
+ function _defineProperty(obj, key, value) {
107
+ key = _toPropertyKey(key);
108
+ if (key in obj) {
109
+ Object.defineProperty(obj, key, {
110
+ value,
111
+ enumerable: true,
112
+ configurable: true,
113
+ writable: true
114
+ });
115
+ } else {
116
+ obj[key] = value;
117
+ }
118
+ return obj;
119
+ }
120
+
121
+ // ../../node_modules/@probe.gl/log/dist/utils/local-storage.js
122
+ function getStorage(type2) {
123
+ try {
124
+ const storage = window[type2];
125
+ const x = "__storage_test__";
126
+ storage.setItem(x, x);
127
+ storage.removeItem(x);
128
+ return storage;
129
+ } catch (e) {
130
+ return null;
131
+ }
132
+ }
133
+ var LocalStorage = class {
134
+ constructor(id, defaultConfig) {
135
+ let type2 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "sessionStorage";
136
+ _defineProperty(this, "storage", void 0);
137
+ _defineProperty(this, "id", void 0);
138
+ _defineProperty(this, "config", void 0);
139
+ this.storage = getStorage(type2);
140
+ this.id = id;
141
+ this.config = defaultConfig;
142
+ this._loadConfiguration();
143
+ }
144
+ getConfiguration() {
145
+ return this.config;
146
+ }
147
+ setConfiguration(configuration) {
148
+ Object.assign(this.config, configuration);
149
+ if (this.storage) {
150
+ const serialized = JSON.stringify(this.config);
151
+ this.storage.setItem(this.id, serialized);
152
+ }
153
+ }
154
+ _loadConfiguration() {
155
+ let configuration = {};
156
+ if (this.storage) {
157
+ const serializedConfiguration = this.storage.getItem(this.id);
158
+ configuration = serializedConfiguration ? JSON.parse(serializedConfiguration) : {};
159
+ }
160
+ Object.assign(this.config, configuration);
161
+ return this;
162
+ }
163
+ };
164
+
165
+ // ../../node_modules/@probe.gl/log/dist/utils/formatters.js
166
+ function formatTime(ms) {
167
+ let formatted;
168
+ if (ms < 10) {
169
+ formatted = "".concat(ms.toFixed(2), "ms");
170
+ } else if (ms < 100) {
171
+ formatted = "".concat(ms.toFixed(1), "ms");
172
+ } else if (ms < 1e3) {
173
+ formatted = "".concat(ms.toFixed(0), "ms");
174
+ } else {
175
+ formatted = "".concat((ms / 1e3).toFixed(2), "s");
176
+ }
177
+ return formatted;
178
+ }
179
+ function leftPad(string) {
180
+ let length = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 8;
181
+ const padLength = Math.max(length - string.length, 0);
182
+ return "".concat(" ".repeat(padLength)).concat(string);
183
+ }
184
+ function formatImage(image, message, scale) {
185
+ let maxWidth = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 600;
186
+ const imageUrl = image.src.replace(/\(/g, "%28").replace(/\)/g, "%29");
187
+ if (image.width > maxWidth) {
188
+ scale = Math.min(scale, maxWidth / image.width);
189
+ }
190
+ const width = image.width * scale;
191
+ const height = image.height * scale;
192
+ const style = ["font-size:1px;", "padding:".concat(Math.floor(height / 2), "px ").concat(Math.floor(width / 2), "px;"), "line-height:".concat(height, "px;"), "background:url(".concat(imageUrl, ");"), "background-size:".concat(width, "px ").concat(height, "px;"), "color:transparent;"].join("");
193
+ return ["".concat(message, " %c+"), style];
194
+ }
195
+
196
+ // ../../node_modules/@probe.gl/log/dist/utils/color.js
197
+ var COLOR;
198
+ (function(COLOR2) {
199
+ COLOR2[COLOR2["BLACK"] = 30] = "BLACK";
200
+ COLOR2[COLOR2["RED"] = 31] = "RED";
201
+ COLOR2[COLOR2["GREEN"] = 32] = "GREEN";
202
+ COLOR2[COLOR2["YELLOW"] = 33] = "YELLOW";
203
+ COLOR2[COLOR2["BLUE"] = 34] = "BLUE";
204
+ COLOR2[COLOR2["MAGENTA"] = 35] = "MAGENTA";
205
+ COLOR2[COLOR2["CYAN"] = 36] = "CYAN";
206
+ COLOR2[COLOR2["WHITE"] = 37] = "WHITE";
207
+ COLOR2[COLOR2["BRIGHT_BLACK"] = 90] = "BRIGHT_BLACK";
208
+ COLOR2[COLOR2["BRIGHT_RED"] = 91] = "BRIGHT_RED";
209
+ COLOR2[COLOR2["BRIGHT_GREEN"] = 92] = "BRIGHT_GREEN";
210
+ COLOR2[COLOR2["BRIGHT_YELLOW"] = 93] = "BRIGHT_YELLOW";
211
+ COLOR2[COLOR2["BRIGHT_BLUE"] = 94] = "BRIGHT_BLUE";
212
+ COLOR2[COLOR2["BRIGHT_MAGENTA"] = 95] = "BRIGHT_MAGENTA";
213
+ COLOR2[COLOR2["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
214
+ COLOR2[COLOR2["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
215
+ })(COLOR || (COLOR = {}));
216
+ var BACKGROUND_INCREMENT = 10;
217
+ function getColor(color) {
218
+ if (typeof color !== "string") {
219
+ return color;
220
+ }
221
+ color = color.toUpperCase();
222
+ return COLOR[color] || COLOR.WHITE;
223
+ }
224
+ function addColor(string, color, background) {
225
+ if (!isBrowser && typeof string === "string") {
226
+ if (color) {
227
+ const colorCode = getColor(color);
228
+ string = "\x1B[".concat(colorCode, "m").concat(string, "\x1B[39m");
229
+ }
230
+ if (background) {
231
+ const colorCode = getColor(background);
232
+ string = "\x1B[".concat(colorCode + BACKGROUND_INCREMENT, "m").concat(string, "\x1B[49m");
233
+ }
234
+ }
235
+ return string;
236
+ }
237
+
238
+ // ../../node_modules/@probe.gl/log/dist/utils/autobind.js
239
+ function autobind(obj) {
240
+ let predefined = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : ["constructor"];
241
+ const proto = Object.getPrototypeOf(obj);
242
+ const propNames = Object.getOwnPropertyNames(proto);
243
+ const object = obj;
244
+ for (const key of propNames) {
245
+ const value = object[key];
246
+ if (typeof value === "function") {
247
+ if (!predefined.find((name) => key === name)) {
248
+ object[key] = value.bind(obj);
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ // ../../node_modules/@probe.gl/log/dist/utils/assert.js
255
+ function assert(condition, message) {
256
+ if (!condition) {
257
+ throw new Error(message || "Assertion failed");
258
+ }
259
+ }
260
+
261
+ // ../../node_modules/@probe.gl/log/dist/utils/hi-res-timestamp.js
262
+ function getHiResTimestamp() {
263
+ let timestamp;
264
+ if (isBrowser() && window_.performance) {
265
+ var _window$performance, _window$performance$n;
266
+ timestamp = window_ === null || window_ === void 0 ? void 0 : (_window$performance = window_.performance) === null || _window$performance === void 0 ? void 0 : (_window$performance$n = _window$performance.now) === null || _window$performance$n === void 0 ? void 0 : _window$performance$n.call(_window$performance);
267
+ } else if ("hrtime" in process_) {
268
+ var _process$hrtime;
269
+ const timeParts = process_ === null || process_ === void 0 ? void 0 : (_process$hrtime = process_.hrtime) === null || _process$hrtime === void 0 ? void 0 : _process$hrtime.call(process_);
270
+ timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
271
+ } else {
272
+ timestamp = Date.now();
273
+ }
274
+ return timestamp;
275
+ }
276
+
277
+ // ../../node_modules/@probe.gl/log/dist/log.js
278
+ var originalConsole = {
279
+ debug: isBrowser() ? console.debug || console.log : console.log,
280
+ log: console.log,
281
+ info: console.info,
282
+ warn: console.warn,
283
+ error: console.error
284
+ };
285
+ var DEFAULT_LOG_CONFIGURATION = {
286
+ enabled: true,
287
+ level: 0
288
+ };
289
+ function noop() {
290
+ }
291
+ var cache = {};
292
+ var ONCE = {
293
+ once: true
294
+ };
295
+ var Log = class {
296
+ constructor() {
297
+ let {
298
+ id
299
+ } = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {
300
+ id: ""
301
+ };
302
+ _defineProperty(this, "id", void 0);
303
+ _defineProperty(this, "VERSION", VERSION);
304
+ _defineProperty(this, "_startTs", getHiResTimestamp());
305
+ _defineProperty(this, "_deltaTs", getHiResTimestamp());
306
+ _defineProperty(this, "_storage", void 0);
307
+ _defineProperty(this, "userData", {});
308
+ _defineProperty(this, "LOG_THROTTLE_TIMEOUT", 0);
309
+ this.id = id;
310
+ this.userData = {};
311
+ this._storage = new LocalStorage("__probe-".concat(this.id, "__"), DEFAULT_LOG_CONFIGURATION);
312
+ this.timeStamp("".concat(this.id, " started"));
313
+ autobind(this);
314
+ Object.seal(this);
315
+ }
316
+ set level(newLevel) {
317
+ this.setLevel(newLevel);
318
+ }
319
+ get level() {
320
+ return this.getLevel();
321
+ }
322
+ isEnabled() {
323
+ return this._storage.config.enabled;
324
+ }
325
+ getLevel() {
326
+ return this._storage.config.level;
327
+ }
328
+ getTotal() {
329
+ return Number((getHiResTimestamp() - this._startTs).toPrecision(10));
330
+ }
331
+ getDelta() {
332
+ return Number((getHiResTimestamp() - this._deltaTs).toPrecision(10));
333
+ }
334
+ set priority(newPriority) {
335
+ this.level = newPriority;
336
+ }
337
+ get priority() {
338
+ return this.level;
339
+ }
340
+ getPriority() {
341
+ return this.level;
342
+ }
343
+ enable() {
344
+ let enabled = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
345
+ this._storage.setConfiguration({
346
+ enabled
347
+ });
348
+ return this;
349
+ }
350
+ setLevel(level) {
351
+ this._storage.setConfiguration({
352
+ level
353
+ });
354
+ return this;
355
+ }
356
+ get(setting) {
357
+ return this._storage.config[setting];
358
+ }
359
+ set(setting, value) {
360
+ this._storage.setConfiguration({
361
+ [setting]: value
362
+ });
363
+ }
364
+ settings() {
365
+ if (console.table) {
366
+ console.table(this._storage.config);
367
+ } else {
368
+ console.log(this._storage.config);
369
+ }
370
+ }
371
+ assert(condition, message) {
372
+ assert(condition, message);
373
+ }
374
+ warn(message) {
375
+ return this._getLogFunction(0, message, originalConsole.warn, arguments, ONCE);
376
+ }
377
+ error(message) {
378
+ return this._getLogFunction(0, message, originalConsole.error, arguments);
379
+ }
380
+ deprecated(oldUsage, newUsage) {
381
+ return this.warn("`".concat(oldUsage, "` is deprecated and will be removed in a later version. Use `").concat(newUsage, "` instead"));
382
+ }
383
+ removed(oldUsage, newUsage) {
384
+ return this.error("`".concat(oldUsage, "` has been removed. Use `").concat(newUsage, "` instead"));
385
+ }
386
+ probe(logLevel, message) {
387
+ return this._getLogFunction(logLevel, message, originalConsole.log, arguments, {
388
+ time: true,
389
+ once: true
390
+ });
391
+ }
392
+ log(logLevel, message) {
393
+ return this._getLogFunction(logLevel, message, originalConsole.debug, arguments);
394
+ }
395
+ info(logLevel, message) {
396
+ return this._getLogFunction(logLevel, message, console.info, arguments);
397
+ }
398
+ once(logLevel, message) {
399
+ return this._getLogFunction(logLevel, message, originalConsole.debug || originalConsole.info, arguments, ONCE);
400
+ }
401
+ table(logLevel, table, columns) {
402
+ if (table) {
403
+ return this._getLogFunction(logLevel, table, console.table || noop, columns && [columns], {
404
+ tag: getTableHeader(table)
405
+ });
406
+ }
407
+ return noop;
408
+ }
409
+ image(_ref) {
410
+ let {
411
+ logLevel,
412
+ priority,
413
+ image,
414
+ message = "",
415
+ scale = 1
416
+ } = _ref;
417
+ if (!this._shouldLog(logLevel || priority)) {
418
+ return noop;
419
+ }
420
+ return isBrowser() ? logImageInBrowser({
421
+ image,
422
+ message,
423
+ scale
424
+ }) : logImageInNode({
425
+ image,
426
+ message,
427
+ scale
428
+ });
429
+ }
430
+ time(logLevel, message) {
431
+ return this._getLogFunction(logLevel, message, console.time ? console.time : console.info);
432
+ }
433
+ timeEnd(logLevel, message) {
434
+ return this._getLogFunction(logLevel, message, console.timeEnd ? console.timeEnd : console.info);
435
+ }
436
+ timeStamp(logLevel, message) {
437
+ return this._getLogFunction(logLevel, message, console.timeStamp || noop);
438
+ }
439
+ group(logLevel, message) {
440
+ let opts = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {
441
+ collapsed: false
442
+ };
443
+ const options = normalizeArguments({
444
+ logLevel,
445
+ message,
446
+ opts
447
+ });
448
+ const {
449
+ collapsed
450
+ } = opts;
451
+ options.method = (collapsed ? console.groupCollapsed : console.group) || console.info;
452
+ return this._getLogFunction(options);
453
+ }
454
+ groupCollapsed(logLevel, message) {
455
+ let opts = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
456
+ return this.group(logLevel, message, Object.assign({}, opts, {
457
+ collapsed: true
458
+ }));
459
+ }
460
+ groupEnd(logLevel) {
461
+ return this._getLogFunction(logLevel, "", console.groupEnd || noop);
462
+ }
463
+ withGroup(logLevel, message, func) {
464
+ this.group(logLevel, message)();
465
+ try {
466
+ func();
467
+ } finally {
468
+ this.groupEnd(logLevel)();
469
+ }
470
+ }
471
+ trace() {
472
+ if (console.trace) {
473
+ console.trace();
474
+ }
475
+ }
476
+ _shouldLog(logLevel) {
477
+ return this.isEnabled() && this.getLevel() >= normalizeLogLevel(logLevel);
478
+ }
479
+ _getLogFunction(logLevel, message, method, args, opts) {
480
+ if (this._shouldLog(logLevel)) {
481
+ opts = normalizeArguments({
482
+ logLevel,
483
+ message,
484
+ args,
485
+ opts
486
+ });
487
+ method = method || opts.method;
488
+ assert(method);
489
+ opts.total = this.getTotal();
490
+ opts.delta = this.getDelta();
491
+ this._deltaTs = getHiResTimestamp();
492
+ const tag = opts.tag || opts.message;
493
+ if (opts.once && tag) {
494
+ if (!cache[tag]) {
495
+ cache[tag] = getHiResTimestamp();
496
+ } else {
497
+ return noop;
498
+ }
499
+ }
500
+ message = decorateMessage(this.id, opts.message, opts);
501
+ return method.bind(console, message, ...opts.args);
502
+ }
503
+ return noop;
504
+ }
505
+ };
506
+ _defineProperty(Log, "VERSION", VERSION);
507
+ function normalizeLogLevel(logLevel) {
508
+ if (!logLevel) {
509
+ return 0;
510
+ }
511
+ let resolvedLevel;
512
+ switch (typeof logLevel) {
513
+ case "number":
514
+ resolvedLevel = logLevel;
515
+ break;
516
+ case "object":
517
+ resolvedLevel = logLevel.logLevel || logLevel.priority || 0;
518
+ break;
519
+ default:
520
+ return 0;
521
+ }
522
+ assert(Number.isFinite(resolvedLevel) && resolvedLevel >= 0);
523
+ return resolvedLevel;
524
+ }
525
+ function normalizeArguments(opts) {
526
+ const {
527
+ logLevel,
528
+ message
529
+ } = opts;
530
+ opts.logLevel = normalizeLogLevel(logLevel);
531
+ const args = opts.args ? Array.from(opts.args) : [];
532
+ while (args.length && args.shift() !== message) {
533
+ }
534
+ switch (typeof logLevel) {
535
+ case "string":
536
+ case "function":
537
+ if (message !== void 0) {
538
+ args.unshift(message);
539
+ }
540
+ opts.message = logLevel;
541
+ break;
542
+ case "object":
543
+ Object.assign(opts, logLevel);
544
+ break;
545
+ default:
546
+ }
547
+ if (typeof opts.message === "function") {
548
+ opts.message = opts.message();
549
+ }
550
+ const messageType = typeof opts.message;
551
+ assert(messageType === "string" || messageType === "object");
552
+ return Object.assign(opts, {
553
+ args
554
+ }, opts.opts);
555
+ }
556
+ function decorateMessage(id, message, opts) {
557
+ if (typeof message === "string") {
558
+ const time = opts.time ? leftPad(formatTime(opts.total)) : "";
559
+ message = opts.time ? "".concat(id, ": ").concat(time, " ").concat(message) : "".concat(id, ": ").concat(message);
560
+ message = addColor(message, opts.color, opts.background);
561
+ }
562
+ return message;
563
+ }
564
+ function logImageInNode(_ref2) {
565
+ let {
566
+ image,
567
+ message = "",
568
+ scale = 1
569
+ } = _ref2;
570
+ console.warn("removed");
571
+ return noop;
572
+ }
573
+ function logImageInBrowser(_ref3) {
574
+ let {
575
+ image,
576
+ message = "",
577
+ scale = 1
578
+ } = _ref3;
579
+ if (typeof image === "string") {
580
+ const img = new Image();
581
+ img.onload = () => {
582
+ const args = formatImage(img, message, scale);
583
+ console.log(...args);
584
+ };
585
+ img.src = image;
586
+ return noop;
587
+ }
588
+ const element = image.nodeName || "";
589
+ if (element.toLowerCase() === "img") {
590
+ console.log(...formatImage(image, message, scale));
591
+ return noop;
592
+ }
593
+ if (element.toLowerCase() === "canvas") {
594
+ const img = new Image();
595
+ img.onload = () => console.log(...formatImage(img, message, scale));
596
+ img.src = image.toDataURL();
597
+ return noop;
598
+ }
599
+ return noop;
600
+ }
601
+ function getTableHeader(table) {
602
+ for (const key in table) {
603
+ for (const title in table[key]) {
604
+ return title || "untitled";
605
+ }
606
+ }
607
+ return "empty";
608
+ }
609
+
610
+ // ../../node_modules/@probe.gl/log/dist/index.js
611
+ var dist_default = new Log({
612
+ id: "@probe.gl/log"
613
+ });
614
+
615
+ // ../api/src/lib/utils/log.ts
616
+ var log = new Log({
617
+ id: "luma.gl"
618
+ });
619
+
620
+ // ../../node_modules/@probe.gl/stats/dist/utils/hi-res-timestamp.js
621
+ function getHiResTimestamp2() {
622
+ let timestamp;
623
+ if (typeof window !== "undefined" && window.performance) {
624
+ timestamp = window.performance.now();
625
+ } else if (typeof process !== "undefined" && process.hrtime) {
626
+ const timeParts = process.hrtime();
627
+ timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
628
+ } else {
629
+ timestamp = Date.now();
630
+ }
631
+ return timestamp;
632
+ }
633
+
634
+ // ../../node_modules/@probe.gl/stats/dist/lib/stat.js
635
+ var Stat = class {
636
+ constructor(name, type2) {
637
+ _defineProperty(this, "name", void 0);
638
+ _defineProperty(this, "type", void 0);
639
+ _defineProperty(this, "sampleSize", 1);
640
+ _defineProperty(this, "time", 0);
641
+ _defineProperty(this, "count", 0);
642
+ _defineProperty(this, "samples", 0);
643
+ _defineProperty(this, "lastTiming", 0);
644
+ _defineProperty(this, "lastSampleTime", 0);
645
+ _defineProperty(this, "lastSampleCount", 0);
646
+ _defineProperty(this, "_count", 0);
647
+ _defineProperty(this, "_time", 0);
648
+ _defineProperty(this, "_samples", 0);
649
+ _defineProperty(this, "_startTime", 0);
650
+ _defineProperty(this, "_timerPending", false);
651
+ this.name = name;
652
+ this.type = type2;
653
+ this.reset();
654
+ }
655
+ reset() {
656
+ this.time = 0;
657
+ this.count = 0;
658
+ this.samples = 0;
659
+ this.lastTiming = 0;
660
+ this.lastSampleTime = 0;
661
+ this.lastSampleCount = 0;
662
+ this._count = 0;
663
+ this._time = 0;
664
+ this._samples = 0;
665
+ this._startTime = 0;
666
+ this._timerPending = false;
667
+ return this;
668
+ }
669
+ setSampleSize(samples) {
670
+ this.sampleSize = samples;
671
+ return this;
672
+ }
673
+ incrementCount() {
674
+ this.addCount(1);
675
+ return this;
676
+ }
677
+ decrementCount() {
678
+ this.subtractCount(1);
679
+ return this;
680
+ }
681
+ addCount(value) {
682
+ this._count += value;
683
+ this._samples++;
684
+ this._checkSampling();
685
+ return this;
686
+ }
687
+ subtractCount(value) {
688
+ this._count -= value;
689
+ this._samples++;
690
+ this._checkSampling();
691
+ return this;
692
+ }
693
+ addTime(time) {
694
+ this._time += time;
695
+ this.lastTiming = time;
696
+ this._samples++;
697
+ this._checkSampling();
698
+ return this;
699
+ }
700
+ timeStart() {
701
+ this._startTime = getHiResTimestamp2();
702
+ this._timerPending = true;
703
+ return this;
704
+ }
705
+ timeEnd() {
706
+ if (!this._timerPending) {
707
+ return this;
708
+ }
709
+ this.addTime(getHiResTimestamp2() - this._startTime);
710
+ this._timerPending = false;
711
+ this._checkSampling();
712
+ return this;
713
+ }
714
+ getSampleAverageCount() {
715
+ return this.sampleSize > 0 ? this.lastSampleCount / this.sampleSize : 0;
716
+ }
717
+ getSampleAverageTime() {
718
+ return this.sampleSize > 0 ? this.lastSampleTime / this.sampleSize : 0;
719
+ }
720
+ getSampleHz() {
721
+ return this.lastSampleTime > 0 ? this.sampleSize / (this.lastSampleTime / 1e3) : 0;
722
+ }
723
+ getAverageCount() {
724
+ return this.samples > 0 ? this.count / this.samples : 0;
725
+ }
726
+ getAverageTime() {
727
+ return this.samples > 0 ? this.time / this.samples : 0;
728
+ }
729
+ getHz() {
730
+ return this.time > 0 ? this.samples / (this.time / 1e3) : 0;
731
+ }
732
+ _checkSampling() {
733
+ if (this._samples === this.sampleSize) {
734
+ this.lastSampleTime = this._time;
735
+ this.lastSampleCount = this._count;
736
+ this.count += this._count;
737
+ this.time += this._time;
738
+ this.samples += this._samples;
739
+ this._time = 0;
740
+ this._count = 0;
741
+ this._samples = 0;
742
+ }
743
+ }
744
+ };
745
+
746
+ // ../../node_modules/@probe.gl/stats/dist/lib/stats.js
747
+ var Stats = class {
748
+ constructor(options) {
749
+ _defineProperty(this, "id", void 0);
750
+ _defineProperty(this, "stats", {});
751
+ this.id = options.id;
752
+ this.stats = {};
753
+ this._initializeStats(options.stats);
754
+ Object.seal(this);
755
+ }
756
+ get(name) {
757
+ let type2 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "count";
758
+ return this._getOrCreate({
759
+ name,
760
+ type: type2
761
+ });
762
+ }
763
+ get size() {
764
+ return Object.keys(this.stats).length;
765
+ }
766
+ reset() {
767
+ for (const stat of Object.values(this.stats)) {
768
+ stat.reset();
769
+ }
770
+ return this;
771
+ }
772
+ forEach(fn) {
773
+ for (const stat of Object.values(this.stats)) {
774
+ fn(stat);
775
+ }
776
+ }
777
+ getTable() {
778
+ const table = {};
779
+ this.forEach((stat) => {
780
+ table[stat.name] = {
781
+ time: stat.time || 0,
782
+ count: stat.count || 0,
783
+ average: stat.getAverageTime() || 0,
784
+ hz: stat.getHz() || 0
785
+ };
786
+ });
787
+ return table;
788
+ }
789
+ _initializeStats() {
790
+ let stats = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : [];
791
+ stats.forEach((stat) => this._getOrCreate(stat));
792
+ }
793
+ _getOrCreate(stat) {
794
+ const {
795
+ name,
796
+ type: type2
797
+ } = stat;
798
+ let result = this.stats[name];
799
+ if (!result) {
800
+ if (stat instanceof Stat) {
801
+ result = stat;
802
+ } else {
803
+ result = new Stat(name, type2);
804
+ }
805
+ this.stats[name] = result;
806
+ }
807
+ return result;
808
+ }
809
+ };
810
+
811
+ // ../api/src/lib/utils/stats-manager.ts
812
+ var StatsManager = class {
813
+ stats = /* @__PURE__ */ new Map();
814
+ getStats(name) {
815
+ return this.get(name);
816
+ }
817
+ get(name) {
818
+ if (!this.stats.has(name)) {
819
+ this.stats.set(name, new Stats({
820
+ id: name
821
+ }));
822
+ }
823
+ return this.stats.get(name);
824
+ }
825
+ };
826
+ var lumaStats = new StatsManager();
827
+
828
+ // ../api/src/init.ts
829
+ function initializeLuma() {
830
+ const VERSION3 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "untranspiled source";
831
+ const STARTUP_MESSAGE = "set luma.log.level=1 (or higher) to trace rendering";
832
+ if (globalThis.luma && globalThis.luma.VERSION !== VERSION3) {
833
+ throw new Error(`luma.gl - multiple VERSIONs detected: ${globalThis.luma.VERSION} vs ${VERSION3}`);
834
+ }
835
+ if (!globalThis.luma) {
836
+ if (isBrowser()) {
837
+ log.log(1, `luma.gl ${VERSION3} - ${STARTUP_MESSAGE}`)();
838
+ }
839
+ globalThis.luma = globalThis.luma || {
840
+ VERSION: VERSION3,
841
+ version: VERSION3,
842
+ log,
843
+ // A global stats object that various components can add information to
844
+ // E.g. see webgl/resource.js
845
+ stats: lumaStats
846
+ };
847
+ }
848
+ return VERSION3;
849
+ }
850
+ var VERSION2 = initializeLuma();
851
+
852
+ // ../api/src/lib/utils/utils.ts
853
+ var uidCounters = {};
854
+ function uid(id = "id") {
855
+ uidCounters[id] = uidCounters[id] || 1;
856
+ const count = uidCounters[id]++;
857
+ return `${id}-${count}`;
858
+ }
859
+ function isObjectEmpty(obj) {
860
+ let isEmpty = true;
861
+ for (const key in obj) {
862
+ isEmpty = false;
863
+ break;
864
+ }
865
+ return isEmpty;
866
+ }
867
+
868
+ // ../api/src/adapter/resources/resource.ts
869
+ var DEFAULT_RESOURCE_PROPS = {
870
+ id: "undefined",
871
+ handle: void 0,
872
+ userData: {}
873
+ };
874
+ var Resource = class {
875
+ /** props.id, for debugging. */
876
+ userData = {};
877
+ destroyed = false;
878
+ /** For resources that allocate GPU memory */
879
+ allocatedBytes = 0;
880
+ /**
881
+ * Create a new Resource. Called from Subclass
882
+ */
883
+ constructor(device, props, defaultProps) {
884
+ if (!device) {
885
+ throw new Error("no device");
886
+ }
887
+ this._device = device;
888
+ this.props = selectivelyMerge(props, defaultProps);
889
+ const id = this.props.id !== "undefined" ? this.props.id : uid(this[Symbol.toStringTag]);
890
+ this.props.id = id;
891
+ this.id = id;
892
+ this.userData = this.props.userData || {};
893
+ this.addStats();
894
+ }
895
+ /**
896
+ * destroy can be called on any resource to release it before it is garbage collected.
897
+ */
898
+ destroy() {
899
+ this.removeStats();
900
+ }
901
+ /** @deprecated Use destroy() */
902
+ delete() {
903
+ this.destroy();
904
+ return this;
905
+ }
906
+ toString() {
907
+ return `${this[Symbol.toStringTag] || this.constructor.name}(${this.id})`;
908
+ }
909
+ /**
910
+ * Combines a map of user props and default props, only including props from defaultProps
911
+ * @returns returns a map of overridden default props
912
+ */
913
+ getProps() {
914
+ return this.props;
915
+ }
916
+ // PROTECTED METHODS
917
+ /** Called by resource constructor to track object creation */
918
+ addStats() {
919
+ const stats = this._device.statsManager.getStats("Resource Counts");
920
+ const name = this[Symbol.toStringTag];
921
+ stats.get("Resources Created").incrementCount();
922
+ stats.get(`${name}s Created`).incrementCount();
923
+ stats.get(`${name}s Active`).incrementCount();
924
+ }
925
+ /** Called by .destroy() to track object destruction. Subclass must call if overriding destroy() */
926
+ removeStats() {
927
+ const stats = this._device.statsManager.getStats("Resource Counts");
928
+ const name = this[Symbol.toStringTag];
929
+ stats.get(`${name}s Active`).decrementCount();
930
+ }
931
+ /** Called by subclass to track memory allocations */
932
+ trackAllocatedMemory(bytes, name = this[Symbol.toStringTag]) {
933
+ const stats = this._device.statsManager.getStats("Resource Counts");
934
+ stats.get("GPU Memory").addCount(bytes);
935
+ stats.get(`${name} Memory`).addCount(bytes);
936
+ this.allocatedBytes = bytes;
937
+ }
938
+ /** Called by subclass to track memory deallocations */
939
+ trackDeallocatedMemory(name = this[Symbol.toStringTag]) {
940
+ const stats = this._device.statsManager.getStats("Resource Counts");
941
+ stats.get("GPU Memory").subtractCount(this.allocatedBytes);
942
+ stats.get(`${name} Memory`).subtractCount(this.allocatedBytes);
943
+ this.allocatedBytes = 0;
944
+ }
945
+ };
946
+ function selectivelyMerge(props, defaultProps) {
947
+ const mergedProps = {
948
+ ...defaultProps
949
+ };
950
+ for (const key in props) {
951
+ if (props[key] !== void 0) {
952
+ mergedProps[key] = props[key];
953
+ }
954
+ }
955
+ return mergedProps;
956
+ }
957
+
958
+ // ../api/src/adapter/resources/buffer.ts
959
+ var DEFAULT_BUFFER_PROPS = {
960
+ ...DEFAULT_RESOURCE_PROPS,
961
+ usage: 0,
962
+ // Buffer.COPY_DST | Buffer.COPY_SRC
963
+ byteLength: 0,
964
+ byteOffset: 0,
965
+ data: null,
966
+ indexType: "uint16",
967
+ mappedAtCreation: false
968
+ };
969
+ var _Buffer = class extends Resource {
970
+ get [Symbol.toStringTag]() {
971
+ return "Buffer";
972
+ }
973
+ constructor(device, props) {
974
+ const deducedProps = {
975
+ ...props
976
+ };
977
+ if ((props.usage || 0) & _Buffer.INDEX && !props.indexType) {
978
+ if (props.data instanceof Uint32Array) {
979
+ deducedProps.indexType = "uint32";
980
+ } else if (props.data instanceof Uint16Array) {
981
+ deducedProps.indexType = "uint16";
982
+ }
983
+ }
984
+ super(device, deducedProps, DEFAULT_BUFFER_PROPS);
985
+ }
986
+ write(data, byteOffset) {
987
+ throw new Error("not implemented");
988
+ }
989
+ readAsync(byteOffset, byteLength) {
990
+ throw new Error("not implemented");
991
+ }
992
+ // TODO - can sync read be supported in WebGPU?
993
+ getData() {
994
+ throw new Error("not implemented");
995
+ }
996
+ // Convenience API
997
+ /** Read data from the buffer *
998
+ async readAsync(options: {
999
+ byteOffset?: number,
1000
+ byteLength?: number,
1001
+ map?: boolean,
1002
+ unmap?: boolean
1003
+ }): Promise<ArrayBuffer> {
1004
+ if (options.map ?? true) {
1005
+ await this.mapAsync(Buffer.MAP_READ, options.byteOffset, options.byteLength);
1006
+ }
1007
+ const arrayBuffer = this.getMappedRange(options.byteOffset, options.byteLength);
1008
+ if (options.unmap ?? true) {
1009
+ this.unmap();
1010
+ }
1011
+ return arrayBuffer;
1012
+ }
1013
+ /** Write data to the buffer *
1014
+ async writeAsync(options: {
1015
+ data: ArrayBuffer,
1016
+ byteOffset?: number,
1017
+ byteLength?: number,
1018
+ map?: boolean,
1019
+ unmap?: boolean
1020
+ }): Promise<void> {
1021
+ if (options.map ?? true) {
1022
+ await this.mapAsync(Buffer.MAP_WRITE, options.byteOffset, options.byteLength);
1023
+ }
1024
+ const arrayBuffer = this.getMappedRange(options.byteOffset, options.byteLength);
1025
+ const destArray = new Uint8Array(arrayBuffer);
1026
+ const srcArray = new Uint8Array(options.data);
1027
+ destArray.set(srcArray);
1028
+ if (options.unmap ?? true) {
1029
+ this.unmap();
1030
+ }
1031
+ }
1032
+ */
1033
+ // Mapped API (WebGPU)
1034
+ /** Maps the memory so that it can be read */
1035
+ // abstract mapAsync(mode, byteOffset, byteLength): Promise<void>
1036
+ /** Get the mapped range of data for reading or writing */
1037
+ // abstract getMappedRange(byteOffset, byteLength): ArrayBuffer;
1038
+ /** unmap makes the contents of the buffer available to the GPU again */
1039
+ // abstract unmap(): void;
1040
+ };
1041
+ var Buffer2 = _Buffer;
1042
+ // Usage Flags
1043
+ __publicField(Buffer2, "MAP_READ", 1);
1044
+ __publicField(Buffer2, "MAP_WRITE", 2);
1045
+ __publicField(Buffer2, "COPY_SRC", 4);
1046
+ __publicField(Buffer2, "COPY_DST", 8);
1047
+ __publicField(Buffer2, "INDEX", 16);
1048
+ __publicField(Buffer2, "VERTEX", 32);
1049
+ __publicField(Buffer2, "UNIFORM", 64);
1050
+ __publicField(Buffer2, "STORAGE", 128);
1051
+ __publicField(Buffer2, "INDIRECT", 256);
1052
+ __publicField(Buffer2, "QUERY_RESOLVE", 512);
1053
+
1054
+ // ../api/src/adapter/device.ts
1055
+ var DEFAULT_DEVICE_PROPS = {
1056
+ id: null,
1057
+ type: "best-available",
1058
+ canvas: null,
1059
+ container: null,
1060
+ webgl2: true,
1061
+ // Attempt to create a WebGL2 context
1062
+ webgl1: true,
1063
+ // Attempt to create a WebGL1 context (false to fail if webgl2 not available)
1064
+ manageState: true,
1065
+ width: 800,
1066
+ // width are height are only used by headless gl
1067
+ height: 600,
1068
+ debug: Boolean(log.get("debug")),
1069
+ // Instrument context (at the expense of performance)
1070
+ break: [],
1071
+ // alpha: undefined,
1072
+ // depth: undefined,
1073
+ // stencil: undefined,
1074
+ // antialias: undefined,
1075
+ // premultipliedAlpha: undefined,
1076
+ // preserveDrawingBuffer: undefined,
1077
+ // failIfMajorPerformanceCaveat: undefined
1078
+ gl: null
1079
+ };
1080
+ var Device = class {
1081
+ get [Symbol.toStringTag]() {
1082
+ return "Device";
1083
+ }
1084
+ constructor(props) {
1085
+ this.props = {
1086
+ ...DEFAULT_DEVICE_PROPS,
1087
+ ...props
1088
+ };
1089
+ this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
1090
+ }
1091
+ statsManager = lumaStats;
1092
+ userData = {};
1093
+ /** Information about the device (vendor, versions etc) */
1094
+ /** Optional capability discovery */
1095
+ /** WebGPU style device limits */
1096
+ /** Check if device supports a specific texture format (creation and `nearest` sampling) */
1097
+ /** Check if linear filtering (sampler interpolation) is supported for a specific texture format */
1098
+ /** Check if device supports rendering to a specific texture format */
1099
+ /** True context is already lost */
1100
+ /** Promise that resolves when context is lost */
1101
+ /** default canvas context */
1102
+ /** Creates a new CanvasContext (WebGPU only) */
1103
+ /** Call after rendering a frame (necessary e.g. on WebGL OffscreenCanvas) */
1104
+ // Resource creation
1105
+ /** Create a buffer */
1106
+ createBuffer(props) {
1107
+ if (props instanceof ArrayBuffer || ArrayBuffer.isView(props)) {
1108
+ return this._createBuffer({
1109
+ data: props
1110
+ });
1111
+ }
1112
+ if ((props.usage || 0) & Buffer2.INDEX && !props.indexType) {
1113
+ if (props.data instanceof Uint32Array) {
1114
+ props.indexType = "uint32";
1115
+ } else if (props.data instanceof Uint16Array) {
1116
+ props.indexType = "uint16";
1117
+ }
1118
+ }
1119
+ return this._createBuffer(props);
1120
+ }
1121
+ /** Create a texture */
1122
+ createTexture(props) {
1123
+ if (props instanceof Promise || typeof props === "string") {
1124
+ props = {
1125
+ data: props
1126
+ };
1127
+ }
1128
+ return this._createTexture(props);
1129
+ }
1130
+ /** Create a temporary texture view of a video source */
1131
+ /** Create a sampler */
1132
+ /** Create a shader */
1133
+ /** Create a render pipeline (aka program) */
1134
+ /** Create a compute pipeline (aka program) */
1135
+ /** Create a RenderPass */
1136
+ /** Create a ComputePass */
1137
+ // Implementation
1138
+ };
1139
+ __publicField(Device, "VERSION", VERSION2);
1140
+
1141
+ // ../api/src/adapter/canvas-context.ts
1142
+ var isPage = isBrowser() && typeof document !== "undefined";
1143
+ var isPageLoaded = () => isPage && document.readyState === "complete";
1144
+ var DEFAULT_CANVAS_CONTEXT_PROPS = {
1145
+ canvas: null,
1146
+ width: 800,
1147
+ // width are height are only used by headless gl
1148
+ height: 600,
1149
+ useDevicePixels: true,
1150
+ autoResize: true,
1151
+ container: null,
1152
+ visible: true,
1153
+ colorSpace: "srgb",
1154
+ alphaMode: "opaque"
1155
+ };
1156
+ var CanvasContext = class {
1157
+ width = 1;
1158
+ height = 1;
1159
+ /** State used by luma.gl classes: TODO - move to canvasContext*/
1160
+ _canvasSizeInfo = {
1161
+ clientWidth: 0,
1162
+ clientHeight: 0,
1163
+ devicePixelRatio: 1
1164
+ };
1165
+ /** Check if the DOM is loaded */
1166
+ static get isPageLoaded() {
1167
+ return isPageLoaded();
1168
+ }
1169
+ constructor(props) {
1170
+ this.props = {
1171
+ ...DEFAULT_CANVAS_CONTEXT_PROPS,
1172
+ ...props
1173
+ };
1174
+ props = this.props;
1175
+ if (!isBrowser()) {
1176
+ this.id = "node-canvas-context";
1177
+ this.type = "node";
1178
+ this.width = this.props.width;
1179
+ this.height = this.props.height;
1180
+ this.canvas = null;
1181
+ return;
1182
+ }
1183
+ if (!props.canvas) {
1184
+ const canvas = createCanvas(props);
1185
+ const container = getContainer(props?.container || null);
1186
+ container.insertBefore(canvas, container.firstChild);
1187
+ this.canvas = canvas;
1188
+ if (!props?.visible) {
1189
+ this.canvas.style.visibility = "hidden";
1190
+ }
1191
+ } else if (typeof props.canvas === "string") {
1192
+ this.canvas = getCanvasFromDOM(props.canvas);
1193
+ } else {
1194
+ this.canvas = props.canvas;
1195
+ }
1196
+ if (this.canvas instanceof HTMLCanvasElement) {
1197
+ this.id = this.canvas.id;
1198
+ this.type = "html-canvas";
1199
+ this.htmlCanvas = this.canvas;
1200
+ } else {
1201
+ this.id = "offscreen-canvas";
1202
+ this.type = "offscreen-canvas";
1203
+ this.offscreenCanvas = this.canvas;
1204
+ }
1205
+ if (this.canvas instanceof HTMLCanvasElement && props.autoResize) {
1206
+ this.resizeObserver = new ResizeObserver((entries) => {
1207
+ for (const entry of entries) {
1208
+ if (entry.target === this.canvas) {
1209
+ this.update();
1210
+ }
1211
+ }
1212
+ });
1213
+ this.resizeObserver.observe(this.canvas);
1214
+ }
1215
+ }
1216
+ /** Returns a framebuffer with properly resized current 'swap chain' textures */
1217
+ /**
1218
+ * Returns the current DPR, if props.useDevicePixels is true
1219
+ * Device refers to physical
1220
+ */
1221
+ getDevicePixelRatio(useDevicePixels) {
1222
+ if (typeof OffscreenCanvas !== "undefined" && this.canvas instanceof OffscreenCanvas) {
1223
+ return 1;
1224
+ }
1225
+ if (typeof useDevicePixels === "number") {
1226
+ return useDevicePixels > 0 ? useDevicePixels : 1;
1227
+ }
1228
+ if (typeof this.props.useDevicePixels === "number") {
1229
+ return this.props.useDevicePixels > 0 ? this.props.useDevicePixels : 1;
1230
+ }
1231
+ return useDevicePixels || this.props.useDevicePixels ? typeof window !== "undefined" && window.devicePixelRatio || 1 : 1;
1232
+ }
1233
+ /**
1234
+ * Returns the size of drawing buffer in device pixels.
1235
+ * @note This can be different from the 'CSS' size of a canvas, and also from the
1236
+ * canvas' internal drawing buffer size (.width, .height).
1237
+ * This is the size required to cover the canvas, adjusted for DPR
1238
+ */
1239
+ getPixelSize() {
1240
+ switch (this.type) {
1241
+ case "node":
1242
+ return [this.width, this.height];
1243
+ case "offscreen-canvas":
1244
+ return [this.canvas.width, this.canvas.height];
1245
+ case "html-canvas":
1246
+ const dpr = this.getDevicePixelRatio();
1247
+ const canvas = this.canvas;
1248
+ return canvas.parentElement ? [canvas.clientWidth * dpr, canvas.clientHeight * dpr] : [this.canvas.width, this.canvas.height];
1249
+ default:
1250
+ throw new Error(this.type);
1251
+ }
1252
+ }
1253
+ getAspect() {
1254
+ const [width, height] = this.getPixelSize();
1255
+ return width / height;
1256
+ }
1257
+ /**
1258
+ * Returns multiplier need to convert CSS size to Device size
1259
+ */
1260
+ cssToDeviceRatio() {
1261
+ try {
1262
+ const [drawingBufferWidth] = this.getDrawingBufferSize();
1263
+ const {
1264
+ clientWidth
1265
+ } = this._canvasSizeInfo;
1266
+ return clientWidth ? drawingBufferWidth / clientWidth : 1;
1267
+ } catch {
1268
+ return 1;
1269
+ }
1270
+ }
1271
+ /**
1272
+ * Maps CSS pixel position to device pixel position
1273
+ */
1274
+ cssToDevicePixels(cssPixel, yInvert = true) {
1275
+ const ratio = this.cssToDeviceRatio();
1276
+ const [width, height] = this.getDrawingBufferSize();
1277
+ return scalePixels(cssPixel, ratio, width, height, yInvert);
1278
+ }
1279
+ /**
1280
+ * Use devicePixelRatio to set canvas width and height
1281
+ * @note this is a raw port of luma.gl v8 code. Might be worth a review
1282
+ */
1283
+ setDevicePixelRatio(devicePixelRatio, options = {}) {
1284
+ if (!this.htmlCanvas) {
1285
+ return;
1286
+ }
1287
+ let clientWidth = "width" in options ? options.width : this.htmlCanvas.clientWidth;
1288
+ let clientHeight = "height" in options ? options.height : this.htmlCanvas.clientHeight;
1289
+ if (!clientWidth || !clientHeight) {
1290
+ log.log(1, "Canvas clientWidth/clientHeight is 0")();
1291
+ devicePixelRatio = 1;
1292
+ clientWidth = this.htmlCanvas.width || 1;
1293
+ clientHeight = this.htmlCanvas.height || 1;
1294
+ }
1295
+ const cachedSize = this._canvasSizeInfo;
1296
+ if (cachedSize.clientWidth !== clientWidth || cachedSize.clientHeight !== clientHeight || cachedSize.devicePixelRatio !== devicePixelRatio) {
1297
+ let clampedPixelRatio = devicePixelRatio;
1298
+ const canvasWidth = Math.floor(clientWidth * clampedPixelRatio);
1299
+ const canvasHeight = Math.floor(clientHeight * clampedPixelRatio);
1300
+ this.htmlCanvas.width = canvasWidth;
1301
+ this.htmlCanvas.height = canvasHeight;
1302
+ const [drawingBufferWidth, drawingBufferHeight] = this.getDrawingBufferSize();
1303
+ if (drawingBufferWidth !== canvasWidth || drawingBufferHeight !== canvasHeight) {
1304
+ clampedPixelRatio = Math.min(drawingBufferWidth / clientWidth, drawingBufferHeight / clientHeight);
1305
+ this.htmlCanvas.width = Math.floor(clientWidth * clampedPixelRatio);
1306
+ this.htmlCanvas.height = Math.floor(clientHeight * clampedPixelRatio);
1307
+ log.warn("Device pixel ratio clamped")();
1308
+ }
1309
+ this._canvasSizeInfo.clientWidth = clientWidth;
1310
+ this._canvasSizeInfo.clientHeight = clientHeight;
1311
+ this._canvasSizeInfo.devicePixelRatio = devicePixelRatio;
1312
+ }
1313
+ }
1314
+ // PRIVATE
1315
+ /** @todo Major hack done to port the CSS methods above, base canvas context should not depend on WebGL */
1316
+ getDrawingBufferSize() {
1317
+ const gl = this.device.gl;
1318
+ if (!gl) {
1319
+ throw new Error("canvas size");
1320
+ }
1321
+ return [gl.drawingBufferWidth, gl.drawingBufferHeight];
1322
+ }
1323
+ /** Perform platform specific updates (WebGPU vs WebGL) */
1324
+ /**
1325
+ * Allows subclass constructor to override the canvas id for auto created canvases.
1326
+ * This can really help when debugging DOM in apps that create multiple devices
1327
+ */
1328
+ _setAutoCreatedCanvasId(id) {
1329
+ if (this.htmlCanvas?.id === "lumagl-auto-created-canvas") {
1330
+ this.htmlCanvas.id = id;
1331
+ }
1332
+ }
1333
+ };
1334
+ /**
1335
+ * Get a 'lazy' promise that resolves when the DOM is loaded.
1336
+ * @note Since there may be limitations on number of `load` event listeners,
1337
+ * it is recommended avoid calling this function until actually needed.
1338
+ * I.e. don't call it until you know that you will be looking up a string in the DOM.
1339
+ */
1340
+ __publicField(CanvasContext, "pageLoaded", getPageLoadPromise());
1341
+ function getPageLoadPromise() {
1342
+ if (isPageLoaded() || typeof window === "undefined") {
1343
+ return Promise.resolve();
1344
+ }
1345
+ return new Promise((resolve) => {
1346
+ window.addEventListener("load", () => resolve());
1347
+ });
1348
+ }
1349
+ function getContainer(container) {
1350
+ if (typeof container === "string") {
1351
+ const element = document.getElementById(container);
1352
+ if (!element && !isPageLoaded()) {
1353
+ throw new Error(`Accessing '${container}' before page was loaded`);
1354
+ }
1355
+ if (!element) {
1356
+ throw new Error(`${container} is not an HTML element`);
1357
+ }
1358
+ return element;
1359
+ } else if (container) {
1360
+ return container;
1361
+ }
1362
+ return document.body;
1363
+ }
1364
+ function getCanvasFromDOM(canvasId) {
1365
+ const canvas = document.getElementById(canvasId);
1366
+ if (!canvas && !isPageLoaded()) {
1367
+ throw new Error(`Accessing '${canvasId}' before page was loaded`);
1368
+ }
1369
+ if (!(canvas instanceof HTMLCanvasElement)) {
1370
+ throw new Error(`'${canvas}' is not a canvas element`);
1371
+ }
1372
+ return canvas;
1373
+ }
1374
+ function createCanvas(props) {
1375
+ const {
1376
+ width,
1377
+ height
1378
+ } = props;
1379
+ const targetCanvas = document.createElement("canvas");
1380
+ targetCanvas.id = "lumagl-auto-created-canvas";
1381
+ targetCanvas.width = width || 1;
1382
+ targetCanvas.height = height || 1;
1383
+ targetCanvas.style.width = Number.isFinite(width) ? `${width}px` : "100%";
1384
+ targetCanvas.style.height = Number.isFinite(height) ? `${height}px` : "100%";
1385
+ return targetCanvas;
1386
+ }
1387
+ function scalePixels(pixel, ratio, width, height, yInvert) {
1388
+ const point = pixel;
1389
+ const x = scaleX(point[0], ratio, width);
1390
+ let y = scaleY(point[1], ratio, height, yInvert);
1391
+ let t = scaleX(point[0] + 1, ratio, width);
1392
+ const xHigh = t === width - 1 ? t : t - 1;
1393
+ t = scaleY(point[1] + 1, ratio, height, yInvert);
1394
+ let yHigh;
1395
+ if (yInvert) {
1396
+ t = t === 0 ? t : t + 1;
1397
+ yHigh = y;
1398
+ y = t;
1399
+ } else {
1400
+ yHigh = t === height - 1 ? t : t - 1;
1401
+ }
1402
+ return {
1403
+ x,
1404
+ y,
1405
+ // when ratio < 1, current css pixel and next css pixel may point to same device pixel, set width/height to 1 in those cases.
1406
+ width: Math.max(xHigh - x + 1, 1),
1407
+ height: Math.max(yHigh - y + 1, 1)
1408
+ };
1409
+ }
1410
+ function scaleX(x, ratio, width) {
1411
+ const r = Math.min(Math.round(x * ratio), width - 1);
1412
+ return r;
1413
+ }
1414
+ function scaleY(y, ratio, height, yInvert) {
1415
+ return yInvert ? Math.max(0, height - 1 - Math.round(y * ratio)) : Math.min(Math.round(y * ratio), height - 1);
1416
+ }
1417
+
1418
+ // ../api/src/adapter/resources/texture.ts
1419
+ var DEFAULT_TEXTURE_PROPS = {
1420
+ ...DEFAULT_RESOURCE_PROPS,
1421
+ data: null,
1422
+ dimension: "2d",
1423
+ format: "rgba8unorm",
1424
+ // width: undefined,
1425
+ // height: undefined,
1426
+ depth: 1,
1427
+ mipmaps: true,
1428
+ sampler: {},
1429
+ // type: undefined,
1430
+ compressed: false,
1431
+ // mipLevels: 1,
1432
+ usage: 0,
1433
+ parameters: {},
1434
+ pixelStore: {},
1435
+ pixels: null,
1436
+ border: 0,
1437
+ recreate: false
1438
+ };
1439
+ var Texture = class extends Resource {
1440
+ get [Symbol.toStringTag]() {
1441
+ return "Texture";
1442
+ }
1443
+ constructor(device, props) {
1444
+ super(device, props, DEFAULT_TEXTURE_PROPS);
1445
+ }
1446
+ /** Default sampler for this device */
1447
+ };
1448
+ __publicField(Texture, "COPY_SRC", 1);
1449
+ __publicField(Texture, "COPY_DST", 2);
1450
+ __publicField(Texture, "TEXTURE_BINDING", 4);
1451
+ __publicField(Texture, "STORAGE_BINDING", 8);
1452
+ __publicField(Texture, "RENDER_ATTACHMENT", 16);
1453
+
1454
+ // ../api/src/adapter/resources/external-texture.ts
1455
+ var DEFAULT_TEXTURE_PROPS2 = {
1456
+ ...DEFAULT_RESOURCE_PROPS,
1457
+ source: null,
1458
+ colorSpace: "srgb"
1459
+ };
1460
+ var ExternalTexture = class extends Resource {
1461
+ get [Symbol.toStringTag]() {
1462
+ return "ExternalTexture";
1463
+ }
1464
+ constructor(device, props) {
1465
+ super(device, props, DEFAULT_TEXTURE_PROPS2);
1466
+ }
1467
+ };
1468
+
1469
+ // ../api/src/adapter/resources/shader.ts
1470
+ var DEFAULT_SHADER_PROPS = {
1471
+ ...DEFAULT_RESOURCE_PROPS,
1472
+ stage: "vertex",
1473
+ source: "",
1474
+ sourceMap: null,
1475
+ language: "glsl",
1476
+ shaderType: 0
1477
+ };
1478
+ var Shader = class extends Resource {
1479
+ get [Symbol.toStringTag]() {
1480
+ return "Shader";
1481
+ }
1482
+ constructor(device, props) {
1483
+ super(device, props, DEFAULT_SHADER_PROPS);
1484
+ this.stage = this.props.stage;
1485
+ this.source = this.props.source;
1486
+ }
1487
+ };
1488
+
1489
+ // ../api/src/adapter/resources/sampler.ts
1490
+ var DEFAULT_SAMPLER_PROPS = {
1491
+ ...DEFAULT_RESOURCE_PROPS,
1492
+ type: "color-sampler",
1493
+ addressModeU: "clamp-to-edge",
1494
+ addressModeV: "clamp-to-edge",
1495
+ addressModeW: "clamp-to-edge",
1496
+ magFilter: "nearest",
1497
+ minFilter: "nearest",
1498
+ mipmapFilter: "nearest",
1499
+ lodMinClamp: 0,
1500
+ lodMaxClamp: 32,
1501
+ // Per WebGPU spec
1502
+ compare: "less-equal",
1503
+ maxAnisotropy: 1
1504
+ };
1505
+ var Sampler = class extends Resource {
1506
+ get [Symbol.toStringTag]() {
1507
+ return "Sampler";
1508
+ }
1509
+ constructor(device, props) {
1510
+ super(device, props, DEFAULT_SAMPLER_PROPS);
1511
+ }
1512
+ };
1513
+
1514
+ // ../api/src/adapter/resources/framebuffer.ts
1515
+ var DEFAULT_FRAMEBUFFER_PROPS = {
1516
+ ...DEFAULT_RESOURCE_PROPS,
1517
+ width: 1,
1518
+ height: 1,
1519
+ colorAttachments: [],
1520
+ // ['rgba8unorm-unsized'],
1521
+ depthStencilAttachment: null
1522
+ // 'depth24plus-stencil8'
1523
+ };
1524
+ var Framebuffer = class extends Resource {
1525
+ get [Symbol.toStringTag]() {
1526
+ return "Framebuffer";
1527
+ }
1528
+ /** Width of all attachments in this framebuffer */
1529
+ /** Height of all attachments in this framebuffer */
1530
+ constructor(device, props = {}) {
1531
+ super(device, props, DEFAULT_FRAMEBUFFER_PROPS);
1532
+ this.width = this.props.width;
1533
+ this.height = this.props.height;
1534
+ }
1535
+ /**
1536
+ * Resizes all attachments
1537
+ * @note resize() destroys existing textures (if size has changed).
1538
+ */
1539
+ resize(size) {
1540
+ const updateSize = !size || size.height !== this.height || size.width !== this.width;
1541
+ if (size) {
1542
+ this.width = size?.width;
1543
+ this.height = size?.height;
1544
+ }
1545
+ if (updateSize) {
1546
+ this._resizeAttachments(this.width, this.height);
1547
+ }
1548
+ }
1549
+ /** Implementation of resize */
1550
+ };
1551
+
1552
+ // ../api/src/adapter/resources/render-pipeline.ts
1553
+ var DEFAULT_RENDER_PIPELINE_PROPS = {
1554
+ ...DEFAULT_RESOURCE_PROPS,
1555
+ vs: null,
1556
+ vsEntryPoint: "",
1557
+ // main
1558
+ vsConstants: {},
1559
+ fs: null,
1560
+ fsEntryPoint: "",
1561
+ // main
1562
+ fsConstants: {},
1563
+ layout: null,
1564
+ // {attributes: [], bindings: []},
1565
+ topology: "triangle-list",
1566
+ // targets:
1567
+ parameters: {},
1568
+ bufferMap: [],
1569
+ vertexCount: 0,
1570
+ instanceCount: 0,
1571
+ indices: null,
1572
+ attributes: {},
1573
+ bindings: {},
1574
+ uniforms: {}
1575
+ };
1576
+ var RenderPipeline = class extends Resource {
1577
+ get [Symbol.toStringTag]() {
1578
+ return "RenderPipeline";
1579
+ }
1580
+ hash = "";
1581
+ constructor(device, props) {
1582
+ super(device, props, DEFAULT_RENDER_PIPELINE_PROPS);
1583
+ }
1584
+ };
1585
+ /** Set attributes (stored on pipeline and set before each call) */
1586
+ /** Set attributes (stored on pipeline and set before each call) */
1587
+ /** Set bindings (stored on pipeline and set before each call) */
1588
+ /** Uniforms (only supported on WebGL devices. Reset before each call to enable pipeline sharing) */
1589
+ /** Draw call */
1590
+ /** Private "export" for Model class */
1591
+ __publicField(RenderPipeline, "_DEFAULT_PROPS", DEFAULT_RENDER_PIPELINE_PROPS);
1592
+
1593
+ // ../api/src/adapter/resources/compute-pipeline.ts
1594
+ var DEFAULT_COMPUTE_PIPELINE_PROPS = {
1595
+ ...DEFAULT_RESOURCE_PROPS,
1596
+ // cs: undefined,
1597
+ // csEntryPoint: undefined,
1598
+ csConstants: {},
1599
+ layout: []
1600
+ };
1601
+ var ComputePipeline = class extends Resource {
1602
+ get [Symbol.toStringTag]() {
1603
+ return "ComputePipeline";
1604
+ }
1605
+ hash = "";
1606
+ constructor(device, props) {
1607
+ super(device, props, DEFAULT_COMPUTE_PIPELINE_PROPS);
1608
+ }
1609
+ };
1610
+
1611
+ // ../api/src/adapter/resources/render-pass.ts
1612
+ var DEFAULT_RENDERPASS_PROPS = {
1613
+ ...DEFAULT_RESOURCE_PROPS,
1614
+ framebuffer: null,
1615
+ parameters: null
1616
+ };
1617
+ var RenderPass = class extends Resource {
1618
+ get [Symbol.toStringTag]() {
1619
+ return "RenderPass";
1620
+ }
1621
+ constructor(device, props) {
1622
+ super(device, props, DEFAULT_RENDERPASS_PROPS);
1623
+ }
1624
+ // writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
1625
+ // beginOcclusionQuery(queryIndex: number): void;
1626
+ // endOcclusionQuery(): void;
1627
+ // executeBundles(bundles: Iterable<GPURenderBundle>): void;
1628
+ // In WebGPU the following methods are on the renderpass.
1629
+ // luma.gl keeps them on the pipeline for now
1630
+ /*
1631
+ setPipeline(pipeline: RenderPipeline): void {}
1632
+ setIndexBuffer(
1633
+ buffer: Buffer,
1634
+ indexFormat: 'uint16' | 'uint32',
1635
+ offset?: number,
1636
+ size?: number
1637
+ ): void {}
1638
+ abstract setVertexBuffer(slot: number, buffer: Buffer, offset: number): void;
1639
+ abstract setBindings(bindings: Record<string, Binding>): void;
1640
+ abstract setParameters(parameters: RenderPassParameters);
1641
+ draw(options: {
1642
+ vertexCount?: number; // Either vertexCount or indexCount must be provided
1643
+ indexCount?: number; // Activates indexed drawing (call setIndexBuffer())
1644
+ instanceCount?: number; //
1645
+ firstVertex?: number;
1646
+ firstIndex?: number; // requires device.features.has('indirect-first-instance')?
1647
+ firstInstance?: number;
1648
+ baseVertex?: number;
1649
+ }): void {}
1650
+ drawIndirect(indirectBuffer: GPUBuffer, indirectOffset: number): void;
1651
+ drawIndexedIndirect(indirectBuffer: GPUBuffer, indirectOffset: number): void;
1652
+ */
1653
+ };
1654
+
1655
+ // ../api/src/adapter/resources/compute-pass.ts
1656
+ var ComputePass = class extends Resource {
1657
+ get [Symbol.toStringTag]() {
1658
+ return "ComputePass";
1659
+ }
1660
+ constructor(device, props) {
1661
+ super(device, props, DEFAULT_RESOURCE_PROPS);
1662
+ }
1663
+ /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
1664
+ // abstract setBindings(bindings: Binding[]): void;
1665
+ /**
1666
+ * Dispatch work to be performed with the current ComputePipeline.
1667
+ * @param x X dimension of the grid of workgroups to dispatch.
1668
+ * @param y Y dimension of the grid of workgroups to dispatch.
1669
+ * @param z Z dimension of the grid of workgroups to dispatch.
1670
+ */
1671
+ /**
1672
+ * Dispatch work to be performed with the current ComputePipeline.
1673
+ * @param indirectBuffer buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
1674
+ * @param indirectOffset
1675
+ */
1676
+ // writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
1677
+ // beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
1678
+ // endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
1679
+ };
1680
+
1681
+ // ../api/src/adapter/utils/decode-data-type.ts
1682
+ function decodeVertexType(type2) {
1683
+ const dataType = TYPE_MAP[type2];
1684
+ const bytes = getDataTypeBytes(dataType);
1685
+ const integer = !type2.startsWith("float");
1686
+ const normalized = type2.includes("norm");
1687
+ const signed = type2.startsWith("s");
1688
+ return {
1689
+ dataType: TYPE_MAP[type2],
1690
+ byteLength: bytes,
1691
+ integer,
1692
+ signed,
1693
+ normalized
1694
+ };
1695
+ }
1696
+ function getDataTypeBytes(type2) {
1697
+ const bytes = TYPE_SIZES[type2];
1698
+ return bytes;
1699
+ }
1700
+ var TYPE_MAP = {
1701
+ uint8: "uint8",
1702
+ sint8: "sint8",
1703
+ unorm8: "uint8",
1704
+ snorm8: "sint8",
1705
+ uint16: "uint16",
1706
+ sint16: "sint16",
1707
+ unorm16: "uint16",
1708
+ snorm16: "sint16",
1709
+ float16: "float16",
1710
+ float32: "float32",
1711
+ uint32: "uint32",
1712
+ sint32: "sint32"
1713
+ };
1714
+ var TYPE_SIZES = {
1715
+ uint8: 1,
1716
+ sint8: 1,
1717
+ uint16: 2,
1718
+ sint16: 2,
1719
+ float16: 2,
1720
+ float32: 4,
1721
+ uint32: 4,
1722
+ sint32: 4
1723
+ };
1724
+
1725
+ // ../api/src/adapter/utils/decode-vertex-format.ts
1726
+ function decodeVertexFormat(format) {
1727
+ const [type_, count] = format.split("x");
1728
+ const type2 = type_;
1729
+ const components = count ? parseInt(count) : 1;
1730
+ const decodedType = decodeVertexType(type2);
1731
+ return {
1732
+ type: type2,
1733
+ components,
1734
+ byteLength: decodedType.byteLength * components,
1735
+ integer: decodedType.integer,
1736
+ signed: decodedType.signed,
1737
+ normalized: decodedType.normalized
1738
+ };
1739
+ }
1740
+
1741
+ // ../api/src/lib/utils/cast.ts
1742
+ function cast(value) {
1743
+ return value;
1744
+ }
1745
+
1746
+ // src/adapter/resources/webgpu-buffer.ts
1747
+ function getByteLength(props) {
1748
+ return props.byteLength || props.data?.byteLength || 0;
1749
+ }
1750
+ var WebGPUBuffer = class extends Buffer2 {
1751
+ constructor(device, props) {
1752
+ super(device, props);
1753
+ this.device = device;
1754
+ this.byteLength = getByteLength(props);
1755
+ const mapBuffer = Boolean(props.data);
1756
+ this.handle = this.props.handle || this.device.handle.createBuffer({
1757
+ size: this.byteLength,
1758
+ // usage defaults to vertex
1759
+ usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
1760
+ mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
1761
+ label: this.props.id
1762
+ });
1763
+ if (props.data) {
1764
+ this._writeMapped(props.data);
1765
+ }
1766
+ if (mapBuffer && !props.mappedAtCreation) {
1767
+ this.handle.unmap();
1768
+ }
1769
+ }
1770
+ destroy() {
1771
+ this.handle.destroy();
1772
+ }
1773
+ // WebGPU provides multiple ways to write a buffer...
1774
+ write(data, byteOffset = 0) {
1775
+ this.device.handle.queue.writeBuffer(this.handle, byteOffset, data.buffer, data.byteOffset, data.byteLength);
1776
+ }
1777
+ async readAsync(byteOffset = 0, byteLength = this.byteLength) {
1778
+ const tempBuffer = new WebGPUBuffer(this.device, {
1779
+ usage: Buffer2.MAP_READ | Buffer2.COPY_DST,
1780
+ byteLength
1781
+ });
1782
+ const commandEncoder = this.device.handle.createCommandEncoder();
1783
+ commandEncoder.copyBufferToBuffer(this.handle, byteOffset, tempBuffer.handle, 0, byteLength);
1784
+ this.device.handle.queue.submit([commandEncoder.finish()]);
1785
+ await tempBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
1786
+ const arrayBuffer = tempBuffer.handle.getMappedRange().slice(0);
1787
+ tempBuffer.handle.unmap();
1788
+ tempBuffer.destroy();
1789
+ return arrayBuffer;
1790
+ }
1791
+ _writeMapped(typedArray) {
1792
+ const arrayBuffer = this.handle.getMappedRange();
1793
+ new typedArray.constructor(arrayBuffer).set(typedArray);
1794
+ }
1795
+ // WEBGPU API
1796
+ mapAsync(mode, offset = 0, size) {
1797
+ return this.handle.mapAsync(mode, offset, size);
1798
+ }
1799
+ getMappedRange(offset = 0, size) {
1800
+ return this.handle.getMappedRange(offset, size);
1801
+ }
1802
+ unmap() {
1803
+ this.handle.unmap();
1804
+ }
1805
+ };
1806
+
1807
+ // src/adapter/helpers/convert-texture-format.ts
1808
+ function getWebGPUTextureFormat(format) {
1809
+ if (format.includes("webgl")) {
1810
+ throw new Error("webgl-only format");
1811
+ }
1812
+ return format;
1813
+ }
1814
+
1815
+ // src/adapter/resources/webgpu-sampler.ts
1816
+ var WebGPUSampler = class extends Sampler {
1817
+ constructor(device, props) {
1818
+ super(device, props);
1819
+ this.device = device;
1820
+ const samplerProps = {
1821
+ ...this.props
1822
+ };
1823
+ if (samplerProps.type !== "comparison-sampler") {
1824
+ delete samplerProps.compare;
1825
+ }
1826
+ this.handle = this.handle || this.device.handle.createSampler(samplerProps);
1827
+ this.handle.label = this.props.id;
1828
+ }
1829
+ destroy() {
1830
+ }
1831
+ };
1832
+
1833
+ // src/adapter/resources/webgpu-texture.ts
1834
+ var BASE_DIMENSIONS = {
1835
+ "1d": "1d",
1836
+ "2d": "2d",
1837
+ "2d-array": "2d",
1838
+ "cube": "2d",
1839
+ "cube-array": "2d",
1840
+ "3d": "3d"
1841
+ };
1842
+ var WebGPUTexture = class extends Texture {
1843
+ // static async createFromImageURL(src, usage = 0) {
1844
+ // const img = document.createElement('img');
1845
+ // img.src = src;
1846
+ // await img.decode();
1847
+ // return WebGPUTexture(img, usage);
1848
+ // }
1849
+ constructor(device, props) {
1850
+ super(device, props);
1851
+ if (typeof this.props.format === "number") {
1852
+ throw new Error("number format");
1853
+ }
1854
+ this.device = device;
1855
+ this.handle = this.props.handle || this.createHandle();
1856
+ if (this.props.data) {
1857
+ this.setData({
1858
+ data: this.props.data
1859
+ });
1860
+ }
1861
+ this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler);
1862
+ this.view = this.handle.createView({
1863
+ // format: this.props.format,
1864
+ // dimension: this.props.dimension,
1865
+ // aspect = "all";
1866
+ // baseMipLevel: 0;
1867
+ // mipLevelCount;
1868
+ // baseArrayLayer = 0;
1869
+ // arrayLayerCount;
1870
+ });
1871
+ }
1872
+ createHandle() {
1873
+ if (typeof this.props.format === "number") {
1874
+ throw new Error("number format");
1875
+ }
1876
+ const width = this.props.width || this.props.data?.width || 1;
1877
+ const height = this.props.height || this.props.data?.height || 1;
1878
+ return this.device.handle.createTexture({
1879
+ size: {
1880
+ width,
1881
+ height,
1882
+ depthOrArrayLayers: this.props.depth
1883
+ },
1884
+ dimension: BASE_DIMENSIONS[this.props.dimension],
1885
+ format: getWebGPUTextureFormat(this.props.format),
1886
+ usage: this.props.usage,
1887
+ mipLevelCount: this.props.mipLevels,
1888
+ sampleCount: this.props.samples
1889
+ });
1890
+ }
1891
+ destroy() {
1892
+ this.handle.destroy();
1893
+ }
1894
+ /**
1895
+ * Set default sampler
1896
+ * Accept a sampler instance or set of props;
1897
+ */
1898
+ setSampler(sampler) {
1899
+ this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
1900
+ return this;
1901
+ }
1902
+ setData(options) {
1903
+ return this.setImage({
1904
+ source: options.data
1905
+ });
1906
+ }
1907
+ /** Set image */
1908
+ setImage(options) {
1909
+ const {
1910
+ source,
1911
+ width = options.source.width,
1912
+ height = options.source.height,
1913
+ depth = 1,
1914
+ sourceX = 0,
1915
+ sourceY = 0,
1916
+ mipLevel = 0,
1917
+ x = 0,
1918
+ y = 0,
1919
+ z = 0,
1920
+ aspect = "all",
1921
+ colorSpace = "srgb",
1922
+ premultipliedAlpha = false
1923
+ } = options;
1924
+ this.device.handle.queue.copyExternalImageToTexture(
1925
+ // source: GPUImageCopyExternalImage
1926
+ {
1927
+ source,
1928
+ origin: [sourceX, sourceY]
1929
+ },
1930
+ // destination: GPUImageCopyTextureTagged
1931
+ {
1932
+ texture: this.handle,
1933
+ origin: [x, y, z],
1934
+ mipLevel,
1935
+ aspect,
1936
+ colorSpace,
1937
+ premultipliedAlpha
1938
+ },
1939
+ // copySize: GPUExtent3D
1940
+ [width, height, depth]
1941
+ );
1942
+ return this;
1943
+ }
1944
+ /*
1945
+ async readPixels() {
1946
+ const readbackBuffer = device.createBuffer({
1947
+ usage: Buffer.COPY_DST | Buffer.MAP_READ,
1948
+ size: 4 * textureWidth * textureHeight,
1949
+ });
1950
+ // Copy data from the texture to the buffer.
1951
+ const encoder = device.createCommandEncoder();
1952
+ encoder.copyTextureToBuffer(
1953
+ { texture },
1954
+ { buffer, rowPitch: textureWidth * 4 },
1955
+ [textureWidth, textureHeight],
1956
+ );
1957
+ device.submit([encoder.finish()]);
1958
+ // Get the data on the CPU.
1959
+ await buffer.mapAsync(GPUMapMode.READ);
1960
+ saveScreenshot(buffer.getMappedRange());
1961
+ buffer.unmap();
1962
+ }
1963
+ setImageData(imageData, usage): this {
1964
+ let data = null;
1965
+ const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
1966
+ if (bytesPerRow == img.width * 4) {
1967
+ data = imageData.data;
1968
+ } else {
1969
+ data = new Uint8Array(bytesPerRow * img.height);
1970
+ let imagePixelIndex = 0;
1971
+ for (let y = 0; y < img.height; ++y) {
1972
+ for (let x = 0; x < img.width; ++x) {
1973
+ const i = x * 4 + y * bytesPerRow;
1974
+ data[i] = imageData.data[imagePixelIndex];
1975
+ data[i + 1] = imageData.data[imagePixelIndex + 1];
1976
+ data[i + 2] = imageData.data[imagePixelIndex + 2];
1977
+ data[i + 3] = imageData.data[imagePixelIndex + 3];
1978
+ imagePixelIndex += 4;
1979
+ }
1980
+ }
1981
+ }
1982
+ return this;
1983
+ }
1984
+ setData(data): this {
1985
+ const textureDataBuffer = this.device.handle.createBuffer({
1986
+ size: data.byteLength,
1987
+ usage: Buffer.COPY_DST | Buffer.COPY_SRC,
1988
+ mappedAtCreation: true
1989
+ });
1990
+ new Uint8Array(textureDataBuffer.getMappedRange()).set(data);
1991
+ textureDataBuffer.unmap();
1992
+ this.setBuffer(textureDataBuffer);
1993
+ textureDataBuffer.destroy();
1994
+ return this;
1995
+ }
1996
+ setBuffer(textureDataBuffer, {bytesPerRow}): this {
1997
+ const commandEncoder = this.device.handle.createCommandEncoder();
1998
+ commandEncoder.copyBufferToTexture(
1999
+ {
2000
+ buffer: textureDataBuffer,
2001
+ bytesPerRow
2002
+ },
2003
+ {
2004
+ texture: this.handle
2005
+ },
2006
+ {
2007
+ width,
2008
+ height,
2009
+ depth
2010
+ }
2011
+ );
2012
+ this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
2013
+ return this;
2014
+ }
2015
+ */
2016
+ };
2017
+
2018
+ // src/adapter/resources/webgpu-external-texture.ts
2019
+ var WebGPUExternalTexture = class extends ExternalTexture {
2020
+ constructor(device, props) {
2021
+ super(device, props);
2022
+ this.device = device;
2023
+ this.handle = this.props.handle || this.device.handle.importExternalTexture({
2024
+ source: props.source,
2025
+ colorSpace: props.colorSpace
2026
+ });
2027
+ this.sampler = null;
2028
+ }
2029
+ destroy() {
2030
+ }
2031
+ /** Set default sampler */
2032
+ setSampler(sampler) {
2033
+ this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
2034
+ return this;
2035
+ }
2036
+ };
2037
+
2038
+ // src/adapter/resources/webgpu-shader.ts
2039
+ var WebGPUShader = class extends Shader {
2040
+ constructor(device, props) {
2041
+ super(device, props);
2042
+ this.device = device;
2043
+ this.device.handle.pushErrorScope("validation");
2044
+ this.handle = this.props.handle || this.createHandle();
2045
+ this.handle.label = this.props.id;
2046
+ this._checkCompilationError(this.device.handle.popErrorScope());
2047
+ }
2048
+ async _checkCompilationError(errorScope) {
2049
+ const error = await errorScope;
2050
+ if (error) {
2051
+ const shaderLog = await this.compilationInfo();
2052
+ log.error(`Shader compilation error: ${error.message}`, shaderLog)();
2053
+ throw new Error(`Shader compilation error: ${error.message}`);
2054
+ }
2055
+ }
2056
+ destroy() {
2057
+ }
2058
+ createHandle() {
2059
+ const {
2060
+ source
2061
+ } = this.props;
2062
+ let language = this.props.language;
2063
+ if (!language) {
2064
+ language = source.includes("->") ? "wgsl" : "glsl";
2065
+ }
2066
+ switch (language) {
2067
+ case "wgsl":
2068
+ return this.device.handle.createShaderModule({
2069
+ code: source
2070
+ });
2071
+ case "glsl":
2072
+ return this.device.handle.createShaderModule({
2073
+ code: source,
2074
+ // @ts-expect-error
2075
+ transform: (glsl) => this.device.glslang.compileGLSL(glsl, type)
2076
+ });
2077
+ default:
2078
+ throw new Error(language);
2079
+ }
2080
+ }
2081
+ /** Returns compilation info for this shader */
2082
+ async compilationInfo() {
2083
+ const compilationInfo = await this.handle.getCompilationInfo();
2084
+ return compilationInfo.messages;
2085
+ }
2086
+ };
2087
+
2088
+ // src/adapter/helpers/webgpu-parameters.ts
2089
+ function addDepthStencil(descriptor) {
2090
+ descriptor.depthStencil = descriptor.depthStencil || {
2091
+ // required, set something
2092
+ format: "depth24plus",
2093
+ stencilFront: {},
2094
+ stencilBack: {},
2095
+ // TODO can this cause trouble? Should we set to WebGPU defaults? Are there defaults?
2096
+ depthWriteEnabled: void 0,
2097
+ depthCompare: void 0
2098
+ };
2099
+ return descriptor.depthStencil;
2100
+ }
2101
+ var PARAMETER_TABLE = {
2102
+ // RASTERIZATION PARAMETERS
2103
+ cullMode: (parameter, value, descriptor) => {
2104
+ descriptor.primitive = descriptor.primitive || {};
2105
+ descriptor.primitive.cullMode = value;
2106
+ },
2107
+ frontFace: (parameter, value, descriptor) => {
2108
+ descriptor.primitive = descriptor.primitive || {};
2109
+ descriptor.primitive.frontFace = value;
2110
+ },
2111
+ // DEPTH
2112
+ depthWriteEnabled: (parameter, value, descriptor) => {
2113
+ const depthStencil = addDepthStencil(descriptor);
2114
+ depthStencil.depthWriteEnabled = value;
2115
+ },
2116
+ depthCompare: (parameter, value, descriptor) => {
2117
+ const depthStencil = addDepthStencil(descriptor);
2118
+ depthStencil.depthCompare = value;
2119
+ },
2120
+ depthFormat: (parameter, value, descriptor) => {
2121
+ const depthStencil = addDepthStencil(descriptor);
2122
+ depthStencil.format = value;
2123
+ },
2124
+ depthBias: (parameter, value, descriptor) => {
2125
+ const depthStencil = addDepthStencil(descriptor);
2126
+ depthStencil.depthBias = value;
2127
+ },
2128
+ depthBiasSlopeScale: (parameter, value, descriptor) => {
2129
+ const depthStencil = addDepthStencil(descriptor);
2130
+ depthStencil.depthBiasSlopeScale = value;
2131
+ },
2132
+ depthBiasClamp: (parameter, value, descriptor) => {
2133
+ const depthStencil = addDepthStencil(descriptor);
2134
+ depthStencil.depthBiasClamp = value;
2135
+ },
2136
+ // STENCIL
2137
+ stencilReadMask: (parameter, value, descriptor) => {
2138
+ const depthStencil = addDepthStencil(descriptor);
2139
+ depthStencil.stencilReadMask = value;
2140
+ },
2141
+ stencilWriteMask: (parameter, value, descriptor) => {
2142
+ const depthStencil = addDepthStencil(descriptor);
2143
+ depthStencil.stencilWriteMask = value;
2144
+ },
2145
+ stencilCompare: (parameter, value, descriptor) => {
2146
+ const depthStencil = addDepthStencil(descriptor);
2147
+ depthStencil.stencilFront.compare = value;
2148
+ depthStencil.stencilBack.compare = value;
2149
+ },
2150
+ stencilPassOperation: (parameter, value, descriptor) => {
2151
+ const depthStencil = addDepthStencil(descriptor);
2152
+ depthStencil.stencilFront.passOp = value;
2153
+ depthStencil.stencilBack.passOp = value;
2154
+ },
2155
+ stencilFailOperation: (parameter, value, descriptor) => {
2156
+ const depthStencil = addDepthStencil(descriptor);
2157
+ depthStencil.stencilFront.failOp = value;
2158
+ depthStencil.stencilBack.failOp = value;
2159
+ },
2160
+ stencilDepthFailOperation: (parameter, value, descriptor) => {
2161
+ const depthStencil = addDepthStencil(descriptor);
2162
+ depthStencil.stencilFront.depthFailOp = value;
2163
+ depthStencil.stencilBack.depthFailOp = value;
2164
+ },
2165
+ // MULTISAMPLE
2166
+ sampleCount: (parameter, value, descriptor) => {
2167
+ descriptor.multisample = descriptor.multisample || {};
2168
+ descriptor.multisample.count = value;
2169
+ },
2170
+ sampleMask: (parameter, value, descriptor) => {
2171
+ descriptor.multisample = descriptor.multisample || {};
2172
+ descriptor.multisample.mask = value;
2173
+ },
2174
+ sampleAlphaToCoverageEnabled: (parameter, value, descriptor) => {
2175
+ descriptor.multisample = descriptor.multisample || {};
2176
+ descriptor.multisample.alphaToCoverageEnabled = value;
2177
+ },
2178
+ // COLOR
2179
+ colorMask: (parameter, value, descriptor) => {
2180
+ const targets = addColorState(descriptor);
2181
+ targets[0].writeMask = value;
2182
+ },
2183
+ blendColorOperation: (parameter, value, descriptor) => {
2184
+ addColorState(descriptor);
2185
+ }
2186
+ /*
2187
+ blendColorSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
2188
+ addColorState(descriptor);
2189
+ targets[0].blend = targets[0].blend || {};
2190
+ targets[0].blend.color = targets[0].blend.color || {};
2191
+ targets[0].blend.color.srcTarget = value;
2192
+ },
2193
+ blendColorDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
2194
+ addColorState(descriptor);
2195
+ targets[0].blend = targets[0].blend || {};
2196
+ targets[0].blend.color = targets[0].blend.color || {};
2197
+ targets[0].blend.color.dstTarget = value;
2198
+ },
2199
+ blendAlphaOperation: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
2200
+ addColorState(descriptor);
2201
+ targets[0].blend = targets[0].blend || {};
2202
+ targets[0].blend.alpha = targets[0].blend.alpha || {};
2203
+ targets[0].blend.alpha.operation = value;
2204
+ },
2205
+ blendAlphaSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
2206
+ addColorState(descriptor);
2207
+ targets[0].blend = targets[0].blend || {};
2208
+ targets[0].blend.alpha = targets[0].blend.alpha || {};
2209
+ targets[0].blend.alpha.srcTarget = value;
2210
+ },
2211
+ blendAlphaDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
2212
+ addColorState(descriptor);
2213
+ targets[0].blend = targets[0].blend || {};
2214
+ targets[0].blend.alpha = targets[0].blend.alpha || {};
2215
+ targets[0].blend.alpha.dstTarget = value;
2216
+ },
2217
+ */
2218
+ };
2219
+ var DEFAULT_PIPELINE_DESCRIPTOR = {
2220
+ // depthStencil: {
2221
+ // stencilFront: {},
2222
+ // stencilBack: {},
2223
+ // // depthWriteEnabled: true,
2224
+ // // depthCompare: 'less',
2225
+ // // format: 'depth24plus-stencil8',
2226
+ // },
2227
+ primitive: {
2228
+ cullMode: "back",
2229
+ topology: "triangle-list"
2230
+ },
2231
+ vertex: {
2232
+ module: void 0,
2233
+ entryPoint: "main"
2234
+ },
2235
+ fragment: {
2236
+ module: void 0,
2237
+ entryPoint: "main",
2238
+ targets: [
2239
+ // { format: props.color0Format || 'bgra8unorm' }
2240
+ ]
2241
+ },
2242
+ layout: "auto"
2243
+ };
2244
+ function applyParametersToRenderPipelineDescriptor(pipelineDescriptor, parameters = {}) {
2245
+ Object.assign(pipelineDescriptor, {
2246
+ ...DEFAULT_PIPELINE_DESCRIPTOR,
2247
+ ...pipelineDescriptor
2248
+ });
2249
+ setParameters(pipelineDescriptor, parameters);
2250
+ }
2251
+ function setParameters(pipelineDescriptor, parameters) {
2252
+ for (const [key, value] of Object.entries(parameters)) {
2253
+ const setterFunction = PARAMETER_TABLE[key];
2254
+ if (!setterFunction) {
2255
+ throw new Error(`Illegal parameter ${key}`);
2256
+ }
2257
+ setterFunction(key, value, pipelineDescriptor);
2258
+ }
2259
+ }
2260
+ function addColorState(descriptor) {
2261
+ descriptor.fragment.targets = descriptor.fragment?.targets || [];
2262
+ if (!Array.isArray(descriptor.fragment?.targets)) {
2263
+ throw new Error("colorstate");
2264
+ }
2265
+ if (descriptor.fragment?.targets?.length === 0) {
2266
+ descriptor.fragment.targets?.push({});
2267
+ }
2268
+ return descriptor.fragment?.targets;
2269
+ }
2270
+
2271
+ // src/adapter/helpers/get-bind-group.ts
2272
+ function getBindGroup(device, bindGroupLayout, layout, bindings) {
2273
+ const entries = getBindGroupEntries(bindings, layout);
2274
+ return device.createBindGroup({
2275
+ layout: bindGroupLayout,
2276
+ entries
2277
+ });
2278
+ }
2279
+ function getShaderLayoutBinding(layout, bindingName) {
2280
+ const bindingLayout = layout.bindings.find((binding) => binding.name === bindingName);
2281
+ if (!bindingLayout) {
2282
+ log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
2283
+ }
2284
+ return bindingLayout;
2285
+ }
2286
+ function getBindGroupEntries(bindings, layout) {
2287
+ const entries = [];
2288
+ for (const [bindingName, value] of Object.entries(bindings)) {
2289
+ const bindingLayout = getShaderLayoutBinding(layout, bindingName);
2290
+ if (bindingLayout) {
2291
+ entries.push(getBindGroupEntry(value, bindingLayout.location));
2292
+ }
2293
+ }
2294
+ return entries;
2295
+ }
2296
+ function getBindGroupEntry(binding, index) {
2297
+ if (binding instanceof Buffer2) {
2298
+ return {
2299
+ binding: index,
2300
+ resource: {
2301
+ buffer: cast(binding).handle
2302
+ }
2303
+ };
2304
+ }
2305
+ if (binding instanceof Sampler) {
2306
+ return {
2307
+ binding: index,
2308
+ resource: cast(binding).handle
2309
+ };
2310
+ } else if (binding instanceof Texture) {
2311
+ return {
2312
+ binding: index,
2313
+ resource: cast(binding).handle.createView()
2314
+ };
2315
+ }
2316
+ throw new Error("invalid binding");
2317
+ }
2318
+
2319
+ // src/adapter/helpers/get-vertex-buffer-layout.ts
2320
+ function getVertexBufferLayout(layout, bufferMap) {
2321
+ const vertexBufferLayouts = [];
2322
+ const usedAttributes = /* @__PURE__ */ new Set();
2323
+ for (const mapping of bufferMap) {
2324
+ const vertexAttributes = [];
2325
+ let stepMode = "vertex";
2326
+ let byteStride = 0;
2327
+ const byteOffset = mapping.byteOffset || 0;
2328
+ if ("attributes" in mapping) {
2329
+ for (const interleaved of mapping.attributes) {
2330
+ const attributeLayout = findAttributeLayout(layout, interleaved.name, usedAttributes);
2331
+ stepMode = attributeLayout.stepMode || "vertex";
2332
+ vertexAttributes.push({
2333
+ format: attributeLayout.format,
2334
+ offset: byteOffset + byteStride,
2335
+ shaderLocation: attributeLayout.location
2336
+ });
2337
+ byteStride += decodeVertexFormat(attributeLayout.format).byteLength;
2338
+ }
2339
+ } else {
2340
+ const attributeLayout = findAttributeLayout(layout, mapping.name, usedAttributes);
2341
+ byteStride = decodeVertexFormat(attributeLayout.format).byteLength;
2342
+ stepMode = attributeLayout.stepMode || "vertex";
2343
+ vertexAttributes.push({
2344
+ format: attributeLayout.format,
2345
+ offset: byteOffset,
2346
+ shaderLocation: attributeLayout.location
2347
+ });
2348
+ }
2349
+ vertexBufferLayouts.push({
2350
+ arrayStride: mapping.byteStride || byteStride,
2351
+ stepMode: stepMode || "vertex",
2352
+ attributes: vertexAttributes
2353
+ });
2354
+ }
2355
+ for (const attribute of layout.attributes) {
2356
+ if (!usedAttributes.has(attribute.name)) {
2357
+ vertexBufferLayouts.push({
2358
+ arrayStride: decodeVertexFormat(attribute.format).byteLength,
2359
+ stepMode: attribute.stepMode || "vertex",
2360
+ attributes: [{
2361
+ format: attribute.format,
2362
+ offset: 0,
2363
+ shaderLocation: attribute.location
2364
+ }]
2365
+ });
2366
+ }
2367
+ }
2368
+ return vertexBufferLayouts;
2369
+ }
2370
+ function getBufferSlots(layout, bufferMap) {
2371
+ const usedAttributes = /* @__PURE__ */ new Set();
2372
+ let bufferSlot = 0;
2373
+ const bufferSlots = {};
2374
+ for (const mapping of bufferMap) {
2375
+ if ("attributes" in mapping) {
2376
+ for (const interleaved of mapping.attributes) {
2377
+ usedAttributes.add(interleaved.name);
2378
+ }
2379
+ } else {
2380
+ usedAttributes.add(mapping.name);
2381
+ }
2382
+ bufferSlots[mapping.name] = bufferSlot++;
2383
+ }
2384
+ for (const attribute of layout.attributes) {
2385
+ if (!usedAttributes.has(attribute.name)) {
2386
+ bufferSlots[attribute.name] = bufferSlot++;
2387
+ }
2388
+ }
2389
+ return bufferSlots;
2390
+ }
2391
+ function findAttributeLayout(layout, name, attributeNames) {
2392
+ const attribute = layout.attributes.find((attribute2) => attribute2.name === name);
2393
+ if (!attribute) {
2394
+ throw new Error(`Unknown attribute ${name}`);
2395
+ }
2396
+ if (attributeNames.has(name)) {
2397
+ throw new Error(`Duplicate attribute ${name}`);
2398
+ }
2399
+ attributeNames.add(name);
2400
+ return attribute;
2401
+ }
2402
+
2403
+ // src/adapter/resources/webgpu-render-pipeline.ts
2404
+ var WebGPURenderPipeline = class extends RenderPipeline {
2405
+ fs = null;
2406
+ _indexBuffer = null;
2407
+ // private _firstIndex: number;
2408
+ // private _lastIndex: number;
2409
+ /** For internal use to create BindGroups */
2410
+ _bindGroup = null;
2411
+ constructor(device, props) {
2412
+ super(device, props);
2413
+ this.device = device;
2414
+ this.handle = this.props.handle || this.createHandle();
2415
+ this.handle.label = this.props.id;
2416
+ this.vs = cast(props.vs);
2417
+ this.fs = cast(props.fs);
2418
+ this._bufferSlots = getBufferSlots(this.props.layout, this.props.bufferMap);
2419
+ this._buffers = new Array(Object.keys(this._bufferSlots).length).fill(null);
2420
+ this._bindGroupLayout = this.handle.getBindGroupLayout(0);
2421
+ }
2422
+ createHandle() {
2423
+ const descriptor = this._getRenderPipelineDescriptor();
2424
+ const renderPipeline = this.device.handle.createRenderPipeline(descriptor);
2425
+ log.groupCollapsed(1, `new WebGPRenderPipeline(${this.id})`)();
2426
+ log.log(1, JSON.stringify(descriptor, null, 2))();
2427
+ log.groupEnd(1)();
2428
+ return renderPipeline;
2429
+ }
2430
+ destroy() {
2431
+ }
2432
+ setIndexBuffer(indexBuffer) {
2433
+ this._indexBuffer = cast(indexBuffer);
2434
+ }
2435
+ setAttributes(attributes) {
2436
+ for (const [name, buffer] of Object.entries(attributes)) {
2437
+ const bufferIndex = this._bufferSlots[name];
2438
+ if (bufferIndex >= 0) {
2439
+ this._buffers[bufferIndex] = buffer;
2440
+ } else {
2441
+ throw new Error(`Setting attribute '${name}' not listed in shader layout for program ${this.id}`);
2442
+ }
2443
+ }
2444
+ }
2445
+ /** Set the bindings */
2446
+ setBindings(bindings) {
2447
+ if (!isObjectEmpty(this.props.bindings)) {
2448
+ Object.assign(this.props.bindings, bindings);
2449
+ this._bindGroup = getBindGroup(this.device.handle, this._bindGroupLayout, this.props.layout, this.props.bindings);
2450
+ }
2451
+ }
2452
+ setUniforms(uniforms) {
2453
+ if (!isObjectEmpty(uniforms)) {
2454
+ throw new Error("WebGPU does not support uniforms");
2455
+ }
2456
+ }
2457
+ _getBuffers() {
2458
+ return this._buffers;
2459
+ }
2460
+ /** Return a bind group created by setBindings */
2461
+ _getBindGroup() {
2462
+ return this._bindGroup;
2463
+ }
2464
+ /** Populate the complex WebGPU GPURenderPipelineDescriptor */
2465
+ _getRenderPipelineDescriptor() {
2466
+ const vertex = {
2467
+ module: cast(this.props.vs).handle,
2468
+ entryPoint: this.props.vsEntryPoint || "main",
2469
+ buffers: getVertexBufferLayout(this.props.layout, this.props.bufferMap)
2470
+ };
2471
+ let fragment;
2472
+ if (this.props.fs) {
2473
+ fragment = {
2474
+ module: cast(this.props.fs).handle,
2475
+ entryPoint: this.props.fsEntryPoint || "main",
2476
+ targets: [{
2477
+ // TODO exclamation mark hack!
2478
+ format: getWebGPUTextureFormat(this.device?.canvasContext?.format)
2479
+ }]
2480
+ };
2481
+ }
2482
+ switch (this.props.topology) {
2483
+ case "triangle-fan":
2484
+ case "line-loop":
2485
+ throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);
2486
+ default:
2487
+ }
2488
+ const descriptor = {
2489
+ vertex,
2490
+ fragment,
2491
+ primitive: {
2492
+ topology: this.props.topology
2493
+ },
2494
+ layout: "auto"
2495
+ };
2496
+ applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
2497
+ return descriptor;
2498
+ }
2499
+ draw(options) {
2500
+ const webgpuRenderPass = cast(options.renderPass) || this.device.getDefaultRenderPass();
2501
+ webgpuRenderPass.handle.setPipeline(this.handle);
2502
+ const bindGroup = this._getBindGroup();
2503
+ if (bindGroup) {
2504
+ webgpuRenderPass.handle.setBindGroup(0, bindGroup);
2505
+ }
2506
+ this._setAttributeBuffers(webgpuRenderPass);
2507
+ if (options.indexCount) {
2508
+ webgpuRenderPass.handle.drawIndexed(options.indexCount, options.instanceCount, options.firstIndex, options.baseVertex, options.firstInstance);
2509
+ } else {
2510
+ webgpuRenderPass.handle.draw(options.vertexCount || 0, options.instanceCount, options.firstIndex, options.firstInstance);
2511
+ }
2512
+ }
2513
+ _setAttributeBuffers(webgpuRenderPass) {
2514
+ if (this._indexBuffer) {
2515
+ webgpuRenderPass.handle.setIndexBuffer(this._indexBuffer.handle, this._indexBuffer.props.indexType);
2516
+ }
2517
+ const buffers = this._getBuffers();
2518
+ for (let i = 0; i < buffers.length; ++i) {
2519
+ const buffer = cast(buffers[i]);
2520
+ if (!buffer) {
2521
+ const attribute = this.props.layout.attributes.find((attribute2) => attribute2.location === i);
2522
+ throw new Error(`No buffer provided for attribute '${attribute?.name || ""}' in Model '${this.props.id}'`);
2523
+ }
2524
+ webgpuRenderPass.handle.setVertexBuffer(i, buffer.handle);
2525
+ }
2526
+ }
2527
+ };
2528
+
2529
+ // src/adapter/resources/webgpu-compute-pipeline.ts
2530
+ var WebGPUComputePipeline = class extends ComputePipeline {
2531
+ constructor(device, props) {
2532
+ super(device, props);
2533
+ this.device = device;
2534
+ const module = cast(this.props.cs).handle;
2535
+ this.handle = this.props.handle || this.device.handle.createComputePipeline({
2536
+ label: this.props.id,
2537
+ compute: {
2538
+ module,
2539
+ entryPoint: this.props.csEntryPoint
2540
+ // constants: this.props.csConstants
2541
+ },
2542
+ layout: "auto"
2543
+ });
2544
+ }
2545
+ /** For internal use in render passes */
2546
+ _getBindGroupLayout() {
2547
+ return this.handle.getBindGroupLayout(0);
2548
+ }
2549
+ };
2550
+
2551
+ // src/adapter/resources/webgpu-render-pass.ts
2552
+ var WebGPURenderPass = class extends RenderPass {
2553
+ /** Active pipeline */
2554
+ pipeline = null;
2555
+ constructor(device, props = {}) {
2556
+ super(device, props);
2557
+ this.device = device;
2558
+ const framebuffer = props.framebuffer || device.canvasContext.getCurrentFramebuffer();
2559
+ const renderPassDescriptor = framebuffer.renderPassDescriptor;
2560
+ this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
2561
+ this.handle.label = this.props.id;
2562
+ }
2563
+ destroy() {
2564
+ }
2565
+ end() {
2566
+ this.handle.end();
2567
+ }
2568
+ setPipeline(pipeline) {
2569
+ this.pipeline = cast(pipeline);
2570
+ this.handle.setPipeline(this.pipeline.handle);
2571
+ }
2572
+ /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
2573
+ setBindings(bindings) {
2574
+ this.pipeline?.setBindings(bindings);
2575
+ const bindGroup = this.pipeline?._getBindGroup();
2576
+ if (bindGroup) {
2577
+ this.handle.setBindGroup(0, bindGroup);
2578
+ }
2579
+ }
2580
+ setIndexBuffer(buffer, indexFormat, offset = 0, size) {
2581
+ this.handle.setIndexBuffer(cast(buffer).handle, indexFormat, offset, size);
2582
+ }
2583
+ setVertexBuffer(slot, buffer, offset = 0) {
2584
+ this.handle.setVertexBuffer(slot, cast(buffer).handle, offset);
2585
+ }
2586
+ draw(options) {
2587
+ if (options.indexCount) {
2588
+ this.handle.drawIndexed(options.indexCount, options.instanceCount, options.firstIndex, options.baseVertex, options.firstInstance);
2589
+ } else {
2590
+ this.handle.draw(options.vertexCount || 0, options.instanceCount, options.firstIndex, options.firstInstance);
2591
+ }
2592
+ }
2593
+ drawIndirect() {
2594
+ }
2595
+ setParameters(parameters) {
2596
+ const {
2597
+ blendConstant,
2598
+ stencilReference,
2599
+ scissorRect,
2600
+ viewport
2601
+ } = parameters;
2602
+ if (blendConstant) {
2603
+ this.handle.setBlendConstant(blendConstant);
2604
+ }
2605
+ if (stencilReference) {
2606
+ this.handle.setStencilReference(stencilReference);
2607
+ }
2608
+ if (scissorRect) {
2609
+ this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
2610
+ }
2611
+ if (viewport) {
2612
+ this.handle.setViewport(viewport[0], viewport[1], viewport[2], viewport[3], viewport[4], viewport[5]);
2613
+ }
2614
+ }
2615
+ pushDebugGroup(groupLabel) {
2616
+ this.handle.pushDebugGroup(groupLabel);
2617
+ }
2618
+ popDebugGroup() {
2619
+ this.handle.popDebugGroup();
2620
+ }
2621
+ insertDebugMarker(markerLabel) {
2622
+ this.handle.insertDebugMarker(markerLabel);
2623
+ }
2624
+ // writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
2625
+ // beginOcclusionQuery(queryIndex: number): void;
2626
+ // endOcclusionQuery(): void;
2627
+ // beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
2628
+ // endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
2629
+ // executeBundles(bundles: Iterable<GPURenderBundle>): void;
2630
+ };
2631
+
2632
+ // src/adapter/resources/webgpu-compute-pass.ts
2633
+ var WebGPUComputePass = class extends ComputePass {
2634
+ _bindGroupLayout = null;
2635
+ constructor(device, props) {
2636
+ super(device, props);
2637
+ this.device = device;
2638
+ this.handle = this.props.handle || device.commandEncoder?.beginComputePass({
2639
+ label: this.props.id
2640
+ // timestampWrites?: GPUComputePassTimestampWrites;
2641
+ });
2642
+ }
2643
+ /** @note no WebGPU destroy method, just gc */
2644
+ destroy() {
2645
+ }
2646
+ end() {
2647
+ this.handle.end();
2648
+ }
2649
+ setPipeline(pipeline) {
2650
+ const wgpuPipeline = cast(pipeline);
2651
+ this.handle.setPipeline(wgpuPipeline.handle);
2652
+ this._bindGroupLayout = wgpuPipeline._getBindGroupLayout();
2653
+ }
2654
+ /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
2655
+ setBindings(bindings) {
2656
+ throw new Error("fix me");
2657
+ }
2658
+ /**
2659
+ * Dispatch work to be performed with the current ComputePipeline.
2660
+ * @param x X dimension of the grid of workgroups to dispatch.
2661
+ * @param y Y dimension of the grid of workgroups to dispatch.
2662
+ * @param z Z dimension of the grid of workgroups to dispatch.
2663
+ */
2664
+ dispatch(x, y, z) {
2665
+ this.handle.dispatchWorkgroups(x, y, z);
2666
+ }
2667
+ /**
2668
+ * Dispatch work to be performed with the current ComputePipeline.
2669
+ * @param indirectBuffer buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
2670
+ * @param indirectOffset
2671
+ */
2672
+ dispatchIndirect(indirectBuffer, indirectOffset = 0) {
2673
+ this.handle.dispatchWorkgroupsIndirect(cast(indirectBuffer).handle, indirectOffset);
2674
+ }
2675
+ pushDebugGroup(groupLabel) {
2676
+ this.handle.pushDebugGroup(groupLabel);
2677
+ }
2678
+ popDebugGroup() {
2679
+ this.handle.popDebugGroup();
2680
+ }
2681
+ insertDebugMarker(markerLabel) {
2682
+ this.handle.insertDebugMarker(markerLabel);
2683
+ }
2684
+ // writeTimestamp(querySet: GPUQuerySet, queryIndex: number): void;
2685
+ // beginPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
2686
+ // endPipelineStatisticsQuery(querySet: GPUQuerySet, queryIndex: number): void;
2687
+ };
2688
+
2689
+ // src/adapter/resources/webgpu-framebuffer.ts
2690
+ var WebGPUFramebuffer = class extends Framebuffer {
2691
+ colorAttachments = [];
2692
+ depthStencilAttachment = null;
2693
+ /** Partial render pass descriptor. Used by WebGPURenderPass */
2694
+ renderPassDescriptor = {
2695
+ colorAttachments: []
2696
+ };
2697
+ constructor(device, props) {
2698
+ super(device, props);
2699
+ this.device = device;
2700
+ if (props.depthStencilAttachment) {
2701
+ this.depthStencilAttachment = this.createDepthStencilTexture(props);
2702
+ }
2703
+ if (props.colorAttachments) {
2704
+ this.colorAttachments = props.colorAttachments.map((colorAttachment) => this.createColorTexture(this.props, colorAttachment));
2705
+ }
2706
+ if (this.depthStencilAttachment) {
2707
+ this.renderPassDescriptor.depthStencilAttachment = {
2708
+ view: this.depthStencilAttachment.handle.createView(),
2709
+ // Add default clear values
2710
+ depthClearValue: 1,
2711
+ depthStoreOp: "store",
2712
+ stencilClearValue: 0,
2713
+ stencilStoreOp: "store"
2714
+ };
2715
+ }
2716
+ if (this.colorAttachments.length > 0) {
2717
+ this.renderPassDescriptor.colorAttachments = this.colorAttachments.map((colorAttachment) => ({
2718
+ view: colorAttachment.handle.createView(),
2719
+ loadOp: "clear",
2720
+ loadValue: [0, 0, 0, 0],
2721
+ storeOp: "store"
2722
+ }));
2723
+ }
2724
+ }
2725
+ /** Create depth stencil texture */
2726
+ createDepthStencilTexture(props) {
2727
+ if (props.depthStencilAttachment instanceof WebGPUTexture) {
2728
+ return props.depthStencilAttachment;
2729
+ }
2730
+ if (typeof props.depthStencilAttachment === "string") {
2731
+ return this.device._createTexture({
2732
+ id: "depth-stencil-attachment",
2733
+ format: props.depthStencilAttachment,
2734
+ width: props.width,
2735
+ height: props.height,
2736
+ usage: Texture.RENDER_ATTACHMENT
2737
+ });
2738
+ }
2739
+ throw new Error("type");
2740
+ }
2741
+ createColorTexture(props, texture) {
2742
+ if (texture instanceof WebGPUTexture) {
2743
+ return texture;
2744
+ }
2745
+ if (typeof texture === "string") {
2746
+ return this.device._createTexture({
2747
+ id: "color-attachment",
2748
+ format: texture,
2749
+ width: props.width,
2750
+ height: props.height,
2751
+ usage: Texture.RENDER_ATTACHMENT
2752
+ });
2753
+ }
2754
+ throw new Error("type");
2755
+ }
2756
+ /**
2757
+ * Create new textures with correct size for all attachments.
2758
+ * @note destroys existing textures.
2759
+ */
2760
+ _resizeAttachments(width, height) {
2761
+ for (let i = 0; i < this.colorAttachments.length; ++i) {
2762
+ if (this.colorAttachments[i]) {
2763
+ const resizedTexture = this.device._createTexture({
2764
+ ...this.colorAttachments[i].props,
2765
+ width,
2766
+ height
2767
+ });
2768
+ this.colorAttachments[i].destroy();
2769
+ this.colorAttachments[i] = resizedTexture;
2770
+ this.renderPassDescriptor.colorAttachments[i].view = resizedTexture.handle.createView();
2771
+ }
2772
+ }
2773
+ if (this.depthStencilAttachment) {
2774
+ const resizedTexture = this.device._createTexture({
2775
+ ...this.depthStencilAttachment.props,
2776
+ width,
2777
+ height
2778
+ });
2779
+ this.depthStencilAttachment.destroy();
2780
+ this.depthStencilAttachment = resizedTexture;
2781
+ this.renderPassDescriptor.depthStencilAttachment.view = resizedTexture.handle.createView();
2782
+ }
2783
+ }
2784
+ };
2785
+
2786
+ // src/adapter/webgpu-canvas-context.ts
2787
+ var WebGPUCanvasContext = class extends CanvasContext {
2788
+ depthStencilFormat = "depth24plus";
2789
+ sampleCount = 1;
2790
+ depthStencilAttachment = null;
2791
+ constructor(device, adapter, props) {
2792
+ super(props);
2793
+ this.device = device;
2794
+ this.width = -1;
2795
+ this.height = -1;
2796
+ this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
2797
+ this.gpuCanvasContext = this.canvas.getContext("webgpu");
2798
+ this.format = this.gpuCanvasContext.getPreferredFormat(adapter);
2799
+ }
2800
+ destroy() {
2801
+ this.gpuCanvasContext.unconfigure();
2802
+ }
2803
+ /** Update framebuffer with properly resized "swap chain" texture views */
2804
+ getCurrentFramebuffer() {
2805
+ this.update();
2806
+ const currentColorAttachment = this.device.createTexture({
2807
+ id: "default-render-target",
2808
+ handle: this.gpuCanvasContext.getCurrentTexture(),
2809
+ format: this.format,
2810
+ width: this.width,
2811
+ height: this.height
2812
+ });
2813
+ this._createDepthStencilAttachment();
2814
+ return new WebGPUFramebuffer(this.device, {
2815
+ colorAttachments: [currentColorAttachment],
2816
+ depthStencilAttachment: this.depthStencilAttachment
2817
+ });
2818
+ }
2819
+ /** Resizes and updates render targets if necessary */
2820
+ update() {
2821
+ const [width, height] = this.getPixelSize();
2822
+ const sizeChanged = width !== this.width || height !== this.height;
2823
+ if (sizeChanged) {
2824
+ this.width = width;
2825
+ this.height = height;
2826
+ if (this.depthStencilAttachment) {
2827
+ this.depthStencilAttachment.destroy();
2828
+ this.depthStencilAttachment = null;
2829
+ }
2830
+ this.gpuCanvasContext.configure({
2831
+ device: this.device.handle,
2832
+ format: getWebGPUTextureFormat(this.format),
2833
+ // size: [this.width, this.height],
2834
+ colorSpace: this.props.colorSpace,
2835
+ alphaMode: this.props.alphaMode
2836
+ });
2837
+ log.log(1, `Resized to ${this.width}x${this.height}px`)();
2838
+ }
2839
+ }
2840
+ resize(options) {
2841
+ this.update();
2842
+ }
2843
+ /** We build render targets on demand (i.e. not when size changes but when about to render) */
2844
+ _createDepthStencilAttachment() {
2845
+ if (!this.depthStencilAttachment) {
2846
+ this.depthStencilAttachment = this.device.createTexture({
2847
+ id: "depth-stencil-target",
2848
+ format: this.depthStencilFormat,
2849
+ width: this.width,
2850
+ height: this.height,
2851
+ usage: GPUTextureUsage.RENDER_ATTACHMENT
2852
+ });
2853
+ }
2854
+ return this.depthStencilAttachment;
2855
+ }
2856
+ };
2857
+
2858
+ // src/adapter/webgpu-device.ts
2859
+ var _WebGPUDevice = class extends Device {
2860
+ canvasContext = null;
2861
+ commandEncoder = null;
2862
+ renderPass = null;
2863
+ _isLost = false;
2864
+ /** Check if WebGPU is available */
2865
+ static isSupported() {
2866
+ return Boolean(typeof navigator !== "undefined" && navigator.gpu);
2867
+ }
2868
+ static async create(props) {
2869
+ if (!navigator.gpu) {
2870
+ throw new Error("WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu");
2871
+ }
2872
+ log.groupCollapsed(1, "WebGPUDevice created")();
2873
+ const adapter = await navigator.gpu.requestAdapter({
2874
+ powerPreference: "high-performance"
2875
+ // forceSoftware: false
2876
+ });
2877
+ if (!adapter) {
2878
+ throw new Error("Failed to request WebGPU adapter");
2879
+ }
2880
+ log.probe(1, "Adapter available")();
2881
+ const gpuDevice = await adapter.requestDevice({
2882
+ requiredFeatures: adapter.features
2883
+ // TODO ensure we obtain best limits
2884
+ // requiredLimits: adapter.limits
2885
+ });
2886
+ log.probe(1, "GPUDevice available")();
2887
+ if (typeof props.canvas === "string") {
2888
+ await CanvasContext.pageLoaded;
2889
+ log.probe(1, "DOM is loaded")();
2890
+ }
2891
+ const device = new _WebGPUDevice(gpuDevice, adapter, props);
2892
+ log.probe(1, "Device created", device.info)();
2893
+ log.table(1, device.info)();
2894
+ log.groupEnd(1)();
2895
+ return device;
2896
+ }
2897
+ constructor(device, adapter, props) {
2898
+ super({
2899
+ ...props,
2900
+ id: props.id || uid("webgpu-device")
2901
+ });
2902
+ this.handle = device;
2903
+ this.adapter = adapter;
2904
+ this._info = {
2905
+ type: "webgpu",
2906
+ vendor: this.adapter.__brand,
2907
+ renderer: "",
2908
+ version: "",
2909
+ gpu: "unknown",
2910
+ // 'nvidia' | 'amd' | 'intel' | 'apple' | 'unknown',
2911
+ shadingLanguages: ["glsl", "wgsl"],
2912
+ shadingLanguageVersions: {
2913
+ glsl: "450",
2914
+ wgsl: "100"
2915
+ },
2916
+ vendorMasked: "",
2917
+ rendererMasked: ""
2918
+ };
2919
+ this.lost = new Promise(async (resolve) => {
2920
+ const lostInfo = await this.handle.lost;
2921
+ this._isLost = true;
2922
+ resolve({
2923
+ reason: "destroyed",
2924
+ message: lostInfo.message
2925
+ });
2926
+ });
2927
+ if (props.canvas) {
2928
+ this.canvasContext = new WebGPUCanvasContext(this, this.adapter, {
2929
+ canvas: props.canvas
2930
+ });
2931
+ }
2932
+ this.features = this._getFeatures();
2933
+ }
2934
+ // TODO
2935
+ // Load the glslang module now so that it is available synchronously when compiling shaders
2936
+ // const {glsl = true} = props;
2937
+ // this.glslang = glsl && await loadGlslangModule();
2938
+ destroy() {
2939
+ this.handle.destroy();
2940
+ }
2941
+ get info() {
2942
+ return this._info;
2943
+ }
2944
+ get limits() {
2945
+ return this.handle.limits;
2946
+ }
2947
+ isTextureFormatSupported(format) {
2948
+ return !format.includes("webgl");
2949
+ }
2950
+ /** @todo implement proper check? */
2951
+ isTextureFormatFilterable(format) {
2952
+ return this.isTextureFormatSupported(format);
2953
+ }
2954
+ /** @todo implement proper check? */
2955
+ isTextureFormatRenderable(format) {
2956
+ return this.isTextureFormatSupported(format);
2957
+ }
2958
+ get isLost() {
2959
+ return this._isLost;
2960
+ }
2961
+ _createBuffer(props) {
2962
+ return new WebGPUBuffer(this, props);
2963
+ }
2964
+ _createTexture(props) {
2965
+ return new WebGPUTexture(this, props);
2966
+ }
2967
+ createExternalTexture(props) {
2968
+ return new WebGPUExternalTexture(this, props);
2969
+ }
2970
+ createShader(props) {
2971
+ return new WebGPUShader(this, props);
2972
+ }
2973
+ createSampler(props) {
2974
+ return new WebGPUSampler(this, props);
2975
+ }
2976
+ createRenderPipeline(props) {
2977
+ return new WebGPURenderPipeline(this, props);
2978
+ }
2979
+ createFramebuffer(props) {
2980
+ throw new Error("Not implemented");
2981
+ }
2982
+ createComputePipeline(props) {
2983
+ return new WebGPUComputePipeline(this, props);
2984
+ }
2985
+ // WebGPU specifics
2986
+ /**
2987
+ * Allows a render pass to begin against a canvas context
2988
+ * @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
2989
+ */
2990
+ beginRenderPass(props) {
2991
+ this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
2992
+ return new WebGPURenderPass(this, props);
2993
+ }
2994
+ beginComputePass(props) {
2995
+ this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
2996
+ return new WebGPUComputePass(this, props);
2997
+ }
2998
+ createCanvasContext(props) {
2999
+ return new WebGPUCanvasContext(this, this.adapter, props);
3000
+ }
3001
+ /**
3002
+ * Gets default renderpass encoder.
3003
+ * Creates a new encoder against default canvasContext if not already created
3004
+ * @note Called internally by Model.
3005
+ */
3006
+ getDefaultRenderPass() {
3007
+ this.renderPass = this.renderPass || this.beginRenderPass({
3008
+ framebuffer: this.canvasContext?.getCurrentFramebuffer()
3009
+ });
3010
+ return this.renderPass;
3011
+ }
3012
+ submit() {
3013
+ this.renderPass?.end();
3014
+ const commandBuffer = this.commandEncoder?.finish();
3015
+ if (commandBuffer) {
3016
+ this.handle.queue.submit([commandBuffer]);
3017
+ }
3018
+ this.commandEncoder = null;
3019
+ this.renderPass = null;
3020
+ }
3021
+ _getFeatures() {
3022
+ const features = new Set(this.handle.features);
3023
+ if (features.has("depth-clamping")) {
3024
+ features.delete("depth-clamping");
3025
+ features.add("depth-clip-control");
3026
+ }
3027
+ if (features.has("texture-compression-bc")) {
3028
+ features.add("texture-compression-bc5-webgl");
3029
+ }
3030
+ features.add("webgpu");
3031
+ features.add("timer-query-webgl");
3032
+ features.add("vertex-array-object-webgl1");
3033
+ features.add("instanced-rendering-webgl1");
3034
+ features.add("multiple-render-targets-webgl1");
3035
+ features.add("index-uint32-webgl1");
3036
+ features.add("blend-minmax-webgl1");
3037
+ features.add("texture-blend-float-webgl1");
3038
+ features.add("texture-formats-srgb-webgl1");
3039
+ features.add("texture-formats-depth-webgl1");
3040
+ features.add("texture-formats-float32-webgl1");
3041
+ features.add("texture-formats-float16-webgl1");
3042
+ features.add("texture-filter-linear-float32-webgl");
3043
+ features.add("texture-filter-linear-float16-webgl");
3044
+ features.add("texture-filter-anisotropic-webgl");
3045
+ features.add("texture-renderable-rgba32float-webgl");
3046
+ features.add("texture-renderable-float32-webgl");
3047
+ features.add("texture-renderable-float16-webgl");
3048
+ features.add("glsl-frag-data");
3049
+ features.add("glsl-frag-depth");
3050
+ features.add("glsl-derivatives");
3051
+ features.add("glsl-texture-lod");
3052
+ return features;
3053
+ }
3054
+ };
3055
+ var WebGPUDevice = _WebGPUDevice;
3056
+ __publicField(WebGPUDevice, "type", "webgpu");
3057
+ return __toCommonJS(src_exports);
3058
+ })();
3059
+ return __exports__;
3060
+ });