@ludicon/spark.js 0.0.13 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/spark.esm.js +438 -286
- package/dist/{utils-Dw9jXlhw.js → utils-_0JXKkpk.js} +110 -13
- package/package.json +1 -1
package/dist/spark.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
Object.entries(
|
|
3
|
-
),
|
|
1
|
+
const V = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import("./spark_astc_rgb-DaSIMKXW.js"), "./spark_astc_rgba.wgsl": () => import("./spark_astc_rgba-BToA2Rcq.js"), "./spark_bc1_rgb.wgsl": () => import("./spark_bc1_rgb-DZwuM1tO.js"), "./spark_bc4_r.wgsl": () => import("./spark_bc4_r-DjThizCH.js"), "./spark_bc5_rg.wgsl": () => import("./spark_bc5_rg-6bO0Gvo9.js"), "./spark_bc7_rgb.wgsl": () => import("./spark_bc7_rgb-FXpBw9fE.js"), "./spark_bc7_rgba.wgsl": () => import("./spark_bc7_rgba-C8Hi2pUY.js"), "./spark_eac_r.wgsl": () => import("./spark_eac_r-D8HGiglc.js"), "./spark_eac_rg.wgsl": () => import("./spark_eac_rg-DvsrLP9h.js"), "./spark_etc2_rgb.wgsl": () => import("./spark_etc2_rgb-C-j5FZpn.js"), "./utils.wgsl": () => import("./utils-_0JXKkpk.js") }), I = Object.fromEntries(
|
|
2
|
+
Object.entries(V).map(([u, e]) => [u.replace("./", ""), async () => (await e()).default])
|
|
3
|
+
), i = {
|
|
4
4
|
ASTC_4x4_RGB: 0,
|
|
5
5
|
ASTC_4x4_RGBA: 1,
|
|
6
6
|
// ASTC_4x4_RGBM: 2,
|
|
@@ -19,7 +19,7 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
19
19
|
// BC6H_RGB: 15,
|
|
20
20
|
BC7_RGB: 16,
|
|
21
21
|
BC7_RGBA: 17
|
|
22
|
-
},
|
|
22
|
+
}, G = [
|
|
23
23
|
/* 0 */
|
|
24
24
|
"astc-4x4-rgb",
|
|
25
25
|
// ASTC_4x4_RGB
|
|
@@ -113,7 +113,7 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
113
113
|
/* 17 */
|
|
114
114
|
"spark_bc7_rgba.wgsl"
|
|
115
115
|
// BC7_RGBA
|
|
116
|
-
],
|
|
116
|
+
], W = [
|
|
117
117
|
/* 0 */
|
|
118
118
|
16,
|
|
119
119
|
// ASTC_4x4_RGB
|
|
@@ -160,7 +160,7 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
160
160
|
/* 17 */
|
|
161
161
|
16
|
|
162
162
|
// BC7_RGB
|
|
163
|
-
],
|
|
163
|
+
], Y = [
|
|
164
164
|
/* 0 */
|
|
165
165
|
4,
|
|
166
166
|
// ASTC_4x4_RGB
|
|
@@ -207,34 +207,34 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
207
207
|
/* 17 */
|
|
208
208
|
4
|
|
209
209
|
// BC7_RGB
|
|
210
|
-
],
|
|
211
|
-
"astc-4x4-rgb":
|
|
212
|
-
"astc-4x4-rgba":
|
|
213
|
-
"eac-r":
|
|
214
|
-
"eac-rg":
|
|
215
|
-
"etc2-rgb":
|
|
216
|
-
"bc1-rgb":
|
|
217
|
-
"bc4-r":
|
|
218
|
-
"bc5-rg":
|
|
219
|
-
"bc7-rgb":
|
|
220
|
-
"bc7-rgba":
|
|
210
|
+
], P = Object.freeze({
|
|
211
|
+
"astc-4x4-rgb": i.ASTC_4x4_RGB,
|
|
212
|
+
"astc-4x4-rgba": i.ASTC_4x4_RGBA,
|
|
213
|
+
"eac-r": i.EAC_R,
|
|
214
|
+
"eac-rg": i.EAC_RG,
|
|
215
|
+
"etc2-rgb": i.ETC2_RGB,
|
|
216
|
+
"bc1-rgb": i.BC1_RGB,
|
|
217
|
+
"bc4-r": i.BC4_R,
|
|
218
|
+
"bc5-rg": i.BC5_RG,
|
|
219
|
+
"bc7-rgb": i.BC7_RGB,
|
|
220
|
+
"bc7-rgba": i.BC7_RGBA,
|
|
221
221
|
// aliases:
|
|
222
|
-
"astc-rgb":
|
|
223
|
-
"astc-rgba":
|
|
222
|
+
"astc-rgb": i.ASTC_4x4_RGB,
|
|
223
|
+
"astc-rgba": i.ASTC_4x4_RGBA,
|
|
224
224
|
// webgpu aliases:
|
|
225
|
-
"bc1-rgba-unorm":
|
|
226
|
-
"bc1-rgba-unorm-srgb":
|
|
227
|
-
"bc4-r-unorm":
|
|
228
|
-
"bc5-rg-unorm":
|
|
229
|
-
"bc7-rgba-unorm":
|
|
230
|
-
"bc7-rgba-unorm-srgb":
|
|
231
|
-
"etc2-rgb8unorm":
|
|
232
|
-
"etc2-rgb8unorm-srgb":
|
|
233
|
-
"eac-r11unorm":
|
|
234
|
-
"eac-rg11unorm":
|
|
235
|
-
"astc-4x4-unorm":
|
|
236
|
-
"astc-4x4-unorm-srgb":
|
|
237
|
-
}),
|
|
225
|
+
"bc1-rgba-unorm": i.BC1_RGB,
|
|
226
|
+
"bc1-rgba-unorm-srgb": i.BC1_RGB,
|
|
227
|
+
"bc4-r-unorm": i.BC4_R,
|
|
228
|
+
"bc5-rg-unorm": i.BC5_RG,
|
|
229
|
+
"bc7-rgba-unorm": i.BC7_RGBA,
|
|
230
|
+
"bc7-rgba-unorm-srgb": i.BC7_RGBA,
|
|
231
|
+
"etc2-rgb8unorm": i.ETC2_RGB,
|
|
232
|
+
"etc2-rgb8unorm-srgb": i.ETC2_RGB,
|
|
233
|
+
"eac-r11unorm": i.EAC_R,
|
|
234
|
+
"eac-rg11unorm": i.EAC_RG,
|
|
235
|
+
"astc-4x4-unorm": i.ASTC_4x4_RGBA,
|
|
236
|
+
"astc-4x4-unorm-srgb": i.ASTC_4x4_RGBA
|
|
237
|
+
}), $ = [
|
|
238
238
|
/* 0 */
|
|
239
239
|
"astc-4x4-unorm",
|
|
240
240
|
// ASTC_4x4_RGB
|
|
@@ -281,7 +281,7 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
281
281
|
/* 17 */
|
|
282
282
|
"bc7-rgba-unorm"
|
|
283
283
|
// BC7_RGB
|
|
284
|
-
],
|
|
284
|
+
], X = [
|
|
285
285
|
/* 0 */
|
|
286
286
|
!0,
|
|
287
287
|
// ASTC_4x4_RGB
|
|
@@ -329,63 +329,66 @@ const z = /* @__PURE__ */ Object.assign({ "./spark_astc_rgb.wgsl": () => import(
|
|
|
329
329
|
!0
|
|
330
330
|
// BC7_RGB
|
|
331
331
|
];
|
|
332
|
-
function w(
|
|
333
|
-
if (!
|
|
332
|
+
function w(u, e) {
|
|
333
|
+
if (!u)
|
|
334
334
|
throw new Error(e);
|
|
335
335
|
}
|
|
336
|
-
function
|
|
337
|
-
return typeof GPUDevice < "u" &&
|
|
336
|
+
function H(u) {
|
|
337
|
+
return typeof GPUDevice < "u" && u instanceof GPUDevice;
|
|
338
338
|
}
|
|
339
|
-
function
|
|
339
|
+
function j() {
|
|
340
340
|
return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
|
|
341
341
|
navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
342
342
|
}
|
|
343
|
-
function
|
|
344
|
-
const
|
|
345
|
-
|
|
343
|
+
function O() {
|
|
344
|
+
const u = navigator.userAgent;
|
|
345
|
+
if (u.includes("Chrome") || u.includes("Chromium"))
|
|
346
|
+
return null;
|
|
347
|
+
const e = u.match(/Safari\/(\d+(\.\d+)?)/);
|
|
348
|
+
return e && parseFloat(e[1]);
|
|
346
349
|
}
|
|
347
|
-
function
|
|
348
|
-
const
|
|
349
|
-
return
|
|
350
|
+
function k() {
|
|
351
|
+
const u = navigator.userAgent.match(/Firefox\/(\d+(\.\d+)?)/);
|
|
352
|
+
return u && parseFloat(u[1]);
|
|
350
353
|
}
|
|
351
|
-
function
|
|
354
|
+
function Q(u) {
|
|
352
355
|
const e = /* @__PURE__ */ new Set(), r = {
|
|
353
356
|
"texture-compression-bc": [
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
i.BC1_RGB,
|
|
358
|
+
i.BC4_R,
|
|
359
|
+
i.BC5_RG,
|
|
360
|
+
i.BC7_RGB,
|
|
361
|
+
i.BC7_RGBA
|
|
359
362
|
],
|
|
360
|
-
"texture-compression-etc2": [
|
|
361
|
-
"texture-compression-astc": [
|
|
363
|
+
"texture-compression-etc2": [i.ETC2_RGB, i.EAC_R, i.EAC_RG],
|
|
364
|
+
"texture-compression-astc": [i.ASTC_4x4_RGB, i.ASTC_4x4_RGBA]
|
|
362
365
|
};
|
|
363
|
-
for (const [t,
|
|
364
|
-
if (
|
|
365
|
-
for (const
|
|
366
|
-
e.add(
|
|
366
|
+
for (const [t, s] of Object.entries(r))
|
|
367
|
+
if (u.features.has(t))
|
|
368
|
+
for (const n of s)
|
|
369
|
+
e.add(n);
|
|
367
370
|
return e;
|
|
368
371
|
}
|
|
369
|
-
function Z(
|
|
372
|
+
function Z(u) {
|
|
370
373
|
const e = document.createElement("canvas");
|
|
371
|
-
e.width =
|
|
374
|
+
e.width = u.width, e.height = u.height;
|
|
372
375
|
const r = e.getContext("2d");
|
|
373
|
-
r.drawImage(
|
|
374
|
-
const t = r.getImageData(0, 0,
|
|
376
|
+
r.drawImage(u, 0, 0);
|
|
377
|
+
const t = r.getImageData(0, 0, u.width, u.height);
|
|
375
378
|
return new Uint8Array(t.data.buffer);
|
|
376
379
|
}
|
|
377
|
-
function J(
|
|
378
|
-
return /\.svg(?:$|\?)/i.test(
|
|
380
|
+
function J(u) {
|
|
381
|
+
return /\.svg(?:$|\?)/i.test(u) || /^data:image\/svg\+xml[,;]/i.test(u);
|
|
379
382
|
}
|
|
380
|
-
function K(
|
|
383
|
+
function K(u) {
|
|
381
384
|
return new Promise((e, r) => {
|
|
382
385
|
const t = new Image();
|
|
383
|
-
t.crossOrigin = "anonymous", t.decoding = "async", t.onload = () => e(t), t.onerror = r, t.src =
|
|
386
|
+
t.crossOrigin = "anonymous", t.decoding = "async", t.onload = () => e(t), t.onerror = r, t.src = u;
|
|
384
387
|
});
|
|
385
388
|
}
|
|
386
|
-
async function ee(
|
|
387
|
-
const r = await fetch(
|
|
388
|
-
if (!r.ok) throw new Error(`HTTP ${r.status} for ${
|
|
389
|
+
async function ee(u, e = {}) {
|
|
390
|
+
const r = await fetch(u, { mode: "cors" });
|
|
391
|
+
if (!r.ok) throw new Error(`HTTP ${r.status} for ${u}`);
|
|
389
392
|
const t = await r.blob();
|
|
390
393
|
return createImageBitmap(t, {
|
|
391
394
|
imageOrientation: e.flipY ? "flipY" : "none",
|
|
@@ -393,35 +396,36 @@ async function ee(n, e = {}) {
|
|
|
393
396
|
premultiplyAlpha: "none"
|
|
394
397
|
});
|
|
395
398
|
}
|
|
396
|
-
const te =
|
|
397
|
-
function
|
|
398
|
-
return J(
|
|
399
|
+
const te = O();
|
|
400
|
+
function N(u) {
|
|
401
|
+
return J(u) || te ? K(u) : ee(u);
|
|
399
402
|
}
|
|
400
|
-
const
|
|
401
|
-
function re(
|
|
402
|
-
let
|
|
403
|
-
const
|
|
403
|
+
const L = 256, F = 4;
|
|
404
|
+
function re(u, e, r, t) {
|
|
405
|
+
let s = 0, n = 0;
|
|
406
|
+
const a = [];
|
|
404
407
|
do {
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
} while (t && (
|
|
408
|
-
return { mipmapCount:
|
|
408
|
+
const o = Math.ceil(u / 4), c = Math.ceil(e / 4), l = Math.ceil(o * r / L) * L, f = c * l;
|
|
409
|
+
s++, a.push({ offset: n, alignedSize: f, w: u, h: e, bw: o, bh: c, bytesPerRow: l }), n += f, u = Math.max(1, Math.floor(u / 2)), e = Math.max(1, Math.floor(e / 2));
|
|
410
|
+
} while (t && (u >= F || e >= F));
|
|
411
|
+
return { mipmapCount: s, outputSize: n, bufferRanges: a };
|
|
409
412
|
}
|
|
410
|
-
class
|
|
413
|
+
class D {
|
|
411
414
|
#e;
|
|
412
|
-
#
|
|
413
|
-
#
|
|
414
|
-
#l;
|
|
415
|
-
#c;
|
|
416
|
-
#m;
|
|
415
|
+
#f;
|
|
416
|
+
#l = [];
|
|
417
417
|
#g;
|
|
418
|
+
#a = !1;
|
|
419
|
+
#s;
|
|
420
|
+
#o;
|
|
418
421
|
#u;
|
|
419
|
-
#
|
|
422
|
+
#m;
|
|
423
|
+
#i;
|
|
420
424
|
#n = new Array(3);
|
|
421
425
|
#r;
|
|
422
|
-
#
|
|
423
|
-
#
|
|
424
|
-
#
|
|
426
|
+
#p;
|
|
427
|
+
#c;
|
|
428
|
+
#G = 0;
|
|
425
429
|
/**
|
|
426
430
|
* Initialize the encoder by detecting available compression formats.
|
|
427
431
|
* @param {GPUDevice} device - WebGPU device.
|
|
@@ -430,7 +434,7 @@ class L {
|
|
|
430
434
|
* @returns {Promise<void>} Resolves when initialization is complete.
|
|
431
435
|
*/
|
|
432
436
|
static async create(e, r = {}) {
|
|
433
|
-
const t = new
|
|
437
|
+
const t = new D();
|
|
434
438
|
return await t.#B(e, r.preload ?? !1, r.useTimestampQueries ?? !1), t;
|
|
435
439
|
}
|
|
436
440
|
/**
|
|
@@ -461,10 +465,10 @@ class L {
|
|
|
461
465
|
"bc7-rgba"
|
|
462
466
|
], r = [];
|
|
463
467
|
for (const t of e) {
|
|
464
|
-
const
|
|
465
|
-
if (this.#t(
|
|
466
|
-
const
|
|
467
|
-
r.push({ format: t, ratio:
|
|
468
|
+
const s = P[t];
|
|
469
|
+
if (this.#t(s)) {
|
|
470
|
+
const n = Y[s];
|
|
471
|
+
r.push({ format: t, ratio: n });
|
|
468
472
|
}
|
|
469
473
|
}
|
|
470
474
|
return r;
|
|
@@ -489,7 +493,7 @@ class L {
|
|
|
489
493
|
*/
|
|
490
494
|
static getRequiredFeatures(e) {
|
|
491
495
|
const r = [];
|
|
492
|
-
return !
|
|
496
|
+
return !j() && e.features.has("texture-compression-bc") && r.push("texture-compression-bc"), e.features.has("texture-compression-etc2") && r.push("texture-compression-etc2"), e.features.has("texture-compression-astc") && r.push("texture-compression-astc"), e.features.has("shader-f16") && r.push("shader-f16"), e.features.has("timestamp-query") && r.push("timestamp-query"), r;
|
|
493
497
|
}
|
|
494
498
|
/**
|
|
495
499
|
* Try to determine the best compression options automatically. Do not use this in production, this is
|
|
@@ -501,10 +505,10 @@ class L {
|
|
|
501
505
|
*/
|
|
502
506
|
async selectPreferredOptions(e, r = {}) {
|
|
503
507
|
if (r.format == null || r.format == "auto") {
|
|
504
|
-
const t = e instanceof Image || e instanceof ImageBitmap || e instanceof GPUTexture ? e : await
|
|
508
|
+
const t = e instanceof Image || e instanceof ImageBitmap || e instanceof GPUTexture ? e : await N(e);
|
|
505
509
|
r.format = "auto";
|
|
506
|
-
const
|
|
507
|
-
r.format =
|
|
510
|
+
const s = await this.#d(r, t);
|
|
511
|
+
r.format = G[s], t instanceof GPUTexture && t.format.endsWith("-srgb") && (r.srgb = !0), (s == i.EAC_RG || s == i.BC5_RG) && (r.normal = !0);
|
|
508
512
|
}
|
|
509
513
|
return r;
|
|
510
514
|
}
|
|
@@ -549,25 +553,26 @@ class L {
|
|
|
549
553
|
*/
|
|
550
554
|
async encodeTexture(e, r = {}) {
|
|
551
555
|
w(this.#e, "Spark is not initialized");
|
|
552
|
-
const t = e instanceof Image || e instanceof ImageBitmap || e instanceof GPUTexture ? e : await
|
|
556
|
+
const t = e instanceof Image || e instanceof ImageBitmap || e instanceof GPUTexture ? e : await N(e);
|
|
553
557
|
console.log("Loaded image", t);
|
|
554
|
-
const
|
|
558
|
+
const s = await this.#d(r, t), n = this.#h(s), a = Math.ceil(t.width / 4) * 4, o = Math.ceil(t.height / 4) * 4, c = W[s], l = r.generateMipmaps || r.mips, { mipmapCount: f, outputSize: h, bufferRanges: m } = re(a, o, c, l), b = (r.srgb || r.format?.endsWith("srgb")) && X[s], _ = b ? 1 : r.normal ? 2 : 0, B = $[s] + (b ? "-srgb" : ""), A = b ? ["rgba8unorm", "rgba8unorm-srgb"] : ["rgba8unorm"], x = this.#G++;
|
|
555
559
|
console.time("create input texture #" + x);
|
|
556
|
-
let
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
560
|
+
let C = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
|
|
561
|
+
this.#a ? C |= GPUTextureUsage.RENDER_ATTACHMENT : C |= GPUTextureUsage.STORAGE_BINDING;
|
|
562
|
+
const y = r.flipY || a != t.width || o != t.height;
|
|
563
|
+
!y && !(t instanceof GPUTexture) && (C |= GPUTextureUsage.RENDER_ATTACHMENT);
|
|
564
|
+
const p = this.#e.createCommandEncoder();
|
|
565
|
+
p.pushDebugGroup?.("spark process texture"), this.#r && typeof p.writeTimestamp == "function" && p.writeTimestamp(this.#r, 0);
|
|
566
|
+
let d;
|
|
567
|
+
(y || !(t instanceof GPUTexture && !l)) && (d = this.#e.createTexture({
|
|
568
|
+
size: [a, o, 1],
|
|
569
|
+
mipLevelCount: f,
|
|
565
570
|
format: "rgba8unorm",
|
|
566
|
-
usage:
|
|
571
|
+
usage: C,
|
|
567
572
|
viewFormats: A
|
|
568
573
|
}));
|
|
569
|
-
let
|
|
570
|
-
|
|
574
|
+
let R;
|
|
575
|
+
y ? t instanceof GPUTexture ? this.#_(p, t, d, a, o, b, r.flipY) : (R = this.#e.createTexture({
|
|
571
576
|
size: [t.width, t.height, 1],
|
|
572
577
|
mipLevelCount: 1,
|
|
573
578
|
format: "rgba8unorm",
|
|
@@ -576,76 +581,76 @@ class L {
|
|
|
576
581
|
viewFormats: A
|
|
577
582
|
}), this.#e.queue.copyExternalImageToTexture(
|
|
578
583
|
{ source: t },
|
|
579
|
-
{ texture:
|
|
584
|
+
{ texture: R },
|
|
580
585
|
{ width: t.width, height: t.height }
|
|
581
|
-
), this.#
|
|
582
|
-
const
|
|
583
|
-
size: [
|
|
584
|
-
mipLevelCount:
|
|
585
|
-
format:
|
|
586
|
+
), this.#_(p, R, d, a, o, _, r.flipY)) : t instanceof GPUTexture ? l ? p.copyTextureToTexture({ texture: t }, { texture: d }, { width: a, height: o }) : d = t : this.#e.queue.copyExternalImageToTexture({ source: t }, { texture: d }, { width: a, height: o }), l && this.#w(p, d, f, a, o, _), p.popDebugGroup?.(), console.timeEnd("create input texture #" + x);
|
|
587
|
+
const E = this.#e.createTexture({
|
|
588
|
+
size: [a, o, 1],
|
|
589
|
+
mipLevelCount: f,
|
|
590
|
+
format: B,
|
|
586
591
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
|
|
587
|
-
}),
|
|
588
|
-
size:
|
|
592
|
+
}), U = this.#e.createBuffer({
|
|
593
|
+
size: h,
|
|
589
594
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
590
|
-
}),
|
|
591
|
-
console.time(
|
|
595
|
+
}), S = `dispatch compute shader '${G[s]}' #${x}`;
|
|
596
|
+
console.time(S), p.pushDebugGroup?.("spark encode texture");
|
|
592
597
|
let M = {};
|
|
593
|
-
this.#r && typeof
|
|
598
|
+
this.#r && typeof p.writeTimestamp != "function" && (M = {
|
|
594
599
|
writeTimestamps: {
|
|
595
600
|
querySet: this.#r,
|
|
596
601
|
beginningOfPassWriteIndex: 0,
|
|
597
602
|
endOfPassWriteIndex: 1
|
|
598
603
|
}
|
|
599
604
|
});
|
|
600
|
-
const
|
|
601
|
-
|
|
602
|
-
for (let
|
|
603
|
-
const
|
|
604
|
-
layout:
|
|
605
|
+
const v = await n, T = p.beginComputePass(M);
|
|
606
|
+
T.setPipeline(v);
|
|
607
|
+
for (let g = 0; g < f; g++) {
|
|
608
|
+
const z = this.#e.createBindGroup({
|
|
609
|
+
layout: v.getBindGroupLayout(0),
|
|
605
610
|
entries: [
|
|
606
611
|
{
|
|
607
612
|
binding: 0,
|
|
608
|
-
resource:
|
|
609
|
-
baseMipLevel:
|
|
613
|
+
resource: d.createView({
|
|
614
|
+
baseMipLevel: g,
|
|
610
615
|
mipLevelCount: 1
|
|
611
616
|
})
|
|
612
617
|
},
|
|
613
618
|
{
|
|
614
619
|
binding: 1,
|
|
615
|
-
resource: this.#
|
|
620
|
+
resource: this.#i
|
|
616
621
|
},
|
|
617
622
|
{
|
|
618
623
|
binding: 2,
|
|
619
624
|
resource: {
|
|
620
|
-
buffer:
|
|
621
|
-
offset: m[
|
|
622
|
-
size: m[
|
|
625
|
+
buffer: U,
|
|
626
|
+
offset: m[g].offset,
|
|
627
|
+
size: m[g].size
|
|
623
628
|
}
|
|
624
629
|
}
|
|
625
630
|
]
|
|
626
631
|
});
|
|
627
|
-
|
|
632
|
+
T.setBindGroup(0, z), T.dispatchWorkgroups(Math.ceil(m[g].bw / 16), Math.ceil(m[g].bh / 16));
|
|
628
633
|
}
|
|
629
|
-
|
|
630
|
-
for (let
|
|
631
|
-
|
|
634
|
+
T.end();
|
|
635
|
+
for (let g = 0; g < f; g++)
|
|
636
|
+
p.copyBufferToTexture(
|
|
632
637
|
{
|
|
633
|
-
buffer:
|
|
634
|
-
offset: m[
|
|
635
|
-
bytesPerRow: m[
|
|
636
|
-
rowsPerImage: m[
|
|
638
|
+
buffer: U,
|
|
639
|
+
offset: m[g].offset,
|
|
640
|
+
bytesPerRow: m[g].bytesPerRow,
|
|
641
|
+
rowsPerImage: m[g].bh
|
|
637
642
|
},
|
|
638
643
|
{
|
|
639
|
-
texture:
|
|
640
|
-
mipLevel:
|
|
644
|
+
texture: E,
|
|
645
|
+
mipLevel: g
|
|
641
646
|
},
|
|
642
647
|
{
|
|
643
|
-
width: m[
|
|
644
|
-
height: m[
|
|
648
|
+
width: m[g].bw * 4,
|
|
649
|
+
height: m[g].bh * 4,
|
|
645
650
|
depthOrArrayLayers: 1
|
|
646
651
|
}
|
|
647
652
|
);
|
|
648
|
-
return this.#r && typeof
|
|
653
|
+
return this.#r && typeof p.writeTimestamp == "function" && p.writeTimestamp(this.#r, 1), p.popDebugGroup?.(), this.#e.queue.submit([p.finish()]), console.timeEnd(S), R?.destroy(), d != t && d?.destroy(), U?.destroy(), E;
|
|
649
654
|
}
|
|
650
655
|
/**
|
|
651
656
|
* Returns the time (in milliseconds) it took to perform the most recent `encodeTexture()` call.
|
|
@@ -670,77 +675,132 @@ class L {
|
|
|
670
675
|
if (!this.#r)
|
|
671
676
|
return 0;
|
|
672
677
|
const e = this.#e.createCommandEncoder();
|
|
673
|
-
e.resolveQuerySet(this.#r, 0, 2, this.#
|
|
674
|
-
const r = this.#
|
|
675
|
-
return this.#
|
|
678
|
+
e.resolveQuerySet(this.#r, 0, 2, this.#p, 0), e.copyBufferToBuffer(this.#p, 0, this.#c, 0, 16), this.#e.queue.submit([e.finish()]), await this.#e.queue.onSubmittedWorkDone(), await this.#c.mapAsync(GPUMapMode.READ);
|
|
679
|
+
const r = this.#c.getMappedRange(), t = new BigUint64Array(r), s = t[0], n = t[1];
|
|
680
|
+
return this.#c.unmap(), Number(n - s) / 1e6;
|
|
676
681
|
}
|
|
677
682
|
async #B(e, r, t) {
|
|
678
|
-
w(e, "device is required"), w(
|
|
683
|
+
w(e, "device is required"), w(H(e), "device is not a WebGPU device"), this.#e = e, this.#f = Q(this.#e), this.#i = this.#e.createSampler({
|
|
679
684
|
magFilter: "linear",
|
|
680
685
|
minFilter: "linear"
|
|
681
686
|
});
|
|
682
|
-
for (let
|
|
683
|
-
this.#n[
|
|
687
|
+
for (let s = 0; s < 3; s++)
|
|
688
|
+
this.#n[s] = this.#e.createBuffer({
|
|
684
689
|
size: 4,
|
|
685
690
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
686
|
-
}), this.#e.queue.writeBuffer(this.#n[
|
|
691
|
+
}), this.#e.queue.writeBuffer(this.#n[s], 0, new Uint32Array([s]));
|
|
687
692
|
if (t && this.#e.features.has("timestamp-query")) {
|
|
688
|
-
const
|
|
689
|
-
(!
|
|
693
|
+
const s = O(), n = k();
|
|
694
|
+
(!s || s >= 26) && !n && (this.#r = this.#e.createQuerySet({
|
|
690
695
|
type: "timestamp",
|
|
691
696
|
count: 2
|
|
692
|
-
}), this.#
|
|
697
|
+
}), this.#p = this.#e.createBuffer({
|
|
693
698
|
size: 16,
|
|
694
699
|
// 2 timestamps × 8 bytes each
|
|
695
700
|
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE
|
|
696
|
-
}), this.#
|
|
701
|
+
}), this.#c = this.#e.createBuffer({
|
|
697
702
|
size: 16,
|
|
698
703
|
// 2 timestamps × 8 bytes each
|
|
699
704
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
700
705
|
}));
|
|
701
706
|
}
|
|
702
|
-
if (this.#
|
|
703
|
-
let
|
|
704
|
-
Array.isArray(r) ?
|
|
705
|
-
for (const
|
|
706
|
-
|
|
707
|
-
console.error(`Failed to preload pipeline for format ${
|
|
707
|
+
if (this.#g = this.#e.features.has("shader-f16"), await this.#C(), r) {
|
|
708
|
+
let s;
|
|
709
|
+
Array.isArray(r) ? s = r.map((n) => this.#b(n, !1)) : s = this.#f;
|
|
710
|
+
for (const n of s)
|
|
711
|
+
n !== void 0 && !this.#l[n] && this.#h(n).catch((a) => {
|
|
712
|
+
console.error(`Failed to preload pipeline for format ${n}:`, a);
|
|
708
713
|
});
|
|
709
714
|
}
|
|
710
715
|
}
|
|
711
|
-
async #
|
|
716
|
+
async #C() {
|
|
712
717
|
const e = this.#e.createShaderModule({
|
|
713
|
-
code: await
|
|
718
|
+
code: await I["utils.wgsl"](),
|
|
714
719
|
label: "utils"
|
|
715
720
|
});
|
|
716
721
|
if (typeof e.compilationInfo == "function") {
|
|
717
|
-
const
|
|
718
|
-
if (
|
|
722
|
+
const t = await e.compilationInfo();
|
|
723
|
+
if (t.messages.some((s) => s.type == "error")) {
|
|
719
724
|
console.error("WGSL compilation errors:");
|
|
720
|
-
for (const
|
|
721
|
-
console.error(
|
|
725
|
+
for (const s of t.messages)
|
|
726
|
+
console.error(s);
|
|
722
727
|
throw new Error("Shader compilation failed");
|
|
723
728
|
}
|
|
724
729
|
}
|
|
725
|
-
this.#
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
730
|
+
if (k() && (this.#a = !0), this.#a) {
|
|
731
|
+
this.#s = {}, this.#o = {}, this.#u = {};
|
|
732
|
+
const t = ["rgba8unorm-srgb", "rgba8unorm"];
|
|
733
|
+
for (const s of t)
|
|
734
|
+
this.#s[s] = this.#e.createRenderPipeline({
|
|
735
|
+
label: `mipmap-pipeline-${s}`,
|
|
736
|
+
layout: "auto",
|
|
737
|
+
vertex: {
|
|
738
|
+
module: e,
|
|
739
|
+
entryPoint: "fullscreen_vs"
|
|
740
|
+
},
|
|
741
|
+
fragment: {
|
|
742
|
+
module: e,
|
|
743
|
+
entryPoint: "mipmap_fs",
|
|
744
|
+
targets: [{ format: s }]
|
|
745
|
+
},
|
|
746
|
+
primitive: {
|
|
747
|
+
topology: "triangle-strip",
|
|
748
|
+
stripIndexFormat: "uint32"
|
|
749
|
+
}
|
|
750
|
+
}), this.#o[s] = this.#e.createRenderPipeline({
|
|
751
|
+
label: `resize-pipeline-${s}`,
|
|
752
|
+
layout: "auto",
|
|
753
|
+
vertex: {
|
|
754
|
+
module: e,
|
|
755
|
+
entryPoint: "fullscreen_vs"
|
|
756
|
+
},
|
|
757
|
+
fragment: {
|
|
758
|
+
module: e,
|
|
759
|
+
entryPoint: "resize_fs",
|
|
760
|
+
targets: [{ format: s }]
|
|
761
|
+
},
|
|
762
|
+
primitive: {
|
|
763
|
+
topology: "triangle-strip",
|
|
764
|
+
stripIndexFormat: "uint32"
|
|
765
|
+
}
|
|
766
|
+
}), this.#u[s] = this.#e.createRenderPipeline({
|
|
767
|
+
label: `flip-y-pipeline-${s}`,
|
|
768
|
+
layout: "auto",
|
|
769
|
+
vertex: {
|
|
770
|
+
module: e,
|
|
771
|
+
entryPoint: "fullscreen_vs"
|
|
772
|
+
},
|
|
773
|
+
fragment: {
|
|
774
|
+
module: e,
|
|
775
|
+
entryPoint: "flipy_fs",
|
|
776
|
+
targets: [{ format: s }]
|
|
777
|
+
},
|
|
778
|
+
primitive: {
|
|
779
|
+
topology: "triangle-strip",
|
|
780
|
+
stripIndexFormat: "uint32"
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
} else
|
|
784
|
+
this.#s = this.#e.createComputePipeline({
|
|
785
|
+
layout: "auto",
|
|
786
|
+
compute: {
|
|
787
|
+
module: e,
|
|
788
|
+
entryPoint: "mipmap"
|
|
789
|
+
}
|
|
790
|
+
}), this.#o = this.#e.createComputePipeline({
|
|
791
|
+
layout: "auto",
|
|
792
|
+
compute: {
|
|
793
|
+
module: e,
|
|
794
|
+
entryPoint: "resize"
|
|
795
|
+
}
|
|
796
|
+
}), this.#u = this.#e.createComputePipeline({
|
|
797
|
+
layout: "auto",
|
|
798
|
+
compute: {
|
|
799
|
+
module: e,
|
|
800
|
+
entryPoint: "flipy"
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
this.#m = await this.#e.createComputePipelineAsync({
|
|
744
804
|
layout: "auto",
|
|
745
805
|
compute: {
|
|
746
806
|
module: e,
|
|
@@ -748,47 +808,47 @@ class L {
|
|
|
748
808
|
}
|
|
749
809
|
});
|
|
750
810
|
}
|
|
751
|
-
async #
|
|
752
|
-
if (this.#
|
|
753
|
-
return this.#
|
|
811
|
+
async #h(e) {
|
|
812
|
+
if (this.#l[e])
|
|
813
|
+
return this.#l[e];
|
|
754
814
|
const r = (async () => {
|
|
755
|
-
console.time("loadPipeline " +
|
|
815
|
+
console.time("loadPipeline " + G[e]);
|
|
756
816
|
const t = q[e];
|
|
757
|
-
w(t, `No shader available for format ${
|
|
758
|
-
let
|
|
759
|
-
this.#
|
|
760
|
-
const
|
|
761
|
-
code:
|
|
762
|
-
label:
|
|
817
|
+
w(t, `No shader available for format ${G[e]}`);
|
|
818
|
+
let s = await I[t]();
|
|
819
|
+
this.#g || (s = s.replace(/^enable f16;\s*/m, "").replace(/\bf16\b/g, "f32").replace(/\bvec([234])h\b/g, "vec$1f").replace(/\bmat([234]x[234])h/g, "mat$1f").replace(/\b(\d*\.\d+|\d+\.)h\b/g, "$1"));
|
|
820
|
+
const n = this.#e.createShaderModule({
|
|
821
|
+
code: s,
|
|
822
|
+
label: G[e]
|
|
763
823
|
});
|
|
764
|
-
if (typeof
|
|
765
|
-
const
|
|
766
|
-
if (
|
|
824
|
+
if (typeof n.getCompilationInfo == "function") {
|
|
825
|
+
const o = await n.getCompilationInfo();
|
|
826
|
+
if (o.messages.some((c) => c.type == "error")) {
|
|
767
827
|
console.error("WGSL compilation errors:");
|
|
768
|
-
for (const
|
|
769
|
-
console.error(
|
|
828
|
+
for (const c of o.messages)
|
|
829
|
+
console.error(c);
|
|
770
830
|
throw new Error("Shader compilation failed");
|
|
771
831
|
}
|
|
772
832
|
}
|
|
773
|
-
const
|
|
833
|
+
const a = await this.#e.createComputePipelineAsync({
|
|
774
834
|
layout: "auto",
|
|
775
835
|
compute: {
|
|
776
|
-
module:
|
|
836
|
+
module: n,
|
|
777
837
|
entryPoint: "main"
|
|
778
838
|
}
|
|
779
839
|
});
|
|
780
|
-
return console.timeEnd("loadPipeline " +
|
|
840
|
+
return console.timeEnd("loadPipeline " + G[e]), a;
|
|
781
841
|
})();
|
|
782
|
-
return this.#
|
|
842
|
+
return this.#l[e] = r, r;
|
|
783
843
|
}
|
|
784
844
|
#t(e) {
|
|
785
|
-
return this.#
|
|
845
|
+
return this.#f.has(e);
|
|
786
846
|
}
|
|
787
|
-
#
|
|
788
|
-
const t =
|
|
847
|
+
#b(e, r) {
|
|
848
|
+
const t = P[e];
|
|
789
849
|
if (t != null && this.#t(t))
|
|
790
850
|
return t;
|
|
791
|
-
const
|
|
851
|
+
const s = r ? [
|
|
792
852
|
"bc4-r",
|
|
793
853
|
"eac-r",
|
|
794
854
|
"bc5-rg",
|
|
@@ -815,100 +875,104 @@ class L {
|
|
|
815
875
|
"astc-rgba",
|
|
816
876
|
"astc-4x4-rgba"
|
|
817
877
|
];
|
|
818
|
-
for (const
|
|
819
|
-
if (
|
|
820
|
-
return
|
|
878
|
+
for (const n of s)
|
|
879
|
+
if (n.includes(e) && this.#t(P[n]))
|
|
880
|
+
return P[n];
|
|
821
881
|
}
|
|
822
|
-
async #
|
|
882
|
+
async #d(e, r) {
|
|
823
883
|
if (e.format == null)
|
|
824
884
|
e.format = "rgb";
|
|
825
885
|
else if (e.format == "auto") {
|
|
826
886
|
if (e.alpha) {
|
|
827
|
-
if (this.#t(
|
|
828
|
-
if (this.#t(
|
|
887
|
+
if (this.#t(i.BC7_RGBA)) return i.BC7_RGBA;
|
|
888
|
+
if (this.#t(i.ASTC_4x4_RGBA)) return i.ASTC_4x4_RGBA;
|
|
829
889
|
} else if (e.srgb) {
|
|
830
|
-
if (this.#t(
|
|
831
|
-
if (this.#t(
|
|
832
|
-
if (this.#t(
|
|
833
|
-
if (this.#t(
|
|
890
|
+
if (this.#t(i.BC7_RGB)) return i.BC7_RGB;
|
|
891
|
+
if (this.#t(i.ASTC_4x4_RGB)) return i.ASTC_4x4_RGB;
|
|
892
|
+
if (this.#t(i.BC1_RGB)) return i.BC1_RGB;
|
|
893
|
+
if (this.#t(i.ETC2_RGB)) return i.ETC2_RGB;
|
|
834
894
|
} else if (e.normal) {
|
|
835
|
-
if (this.#t(
|
|
836
|
-
if (this.#t(
|
|
895
|
+
if (this.#t(i.BC5_RG)) return i.BC5_RG;
|
|
896
|
+
if (this.#t(i.EAC_RG)) return i.EAC_RG;
|
|
837
897
|
} else {
|
|
838
|
-
let
|
|
898
|
+
let s;
|
|
839
899
|
if (r instanceof GPUTexture)
|
|
840
|
-
r.format == "r8unorm" || r.format == "r16unorm" ?
|
|
900
|
+
r.format == "r8unorm" || r.format == "r16unorm" ? s = 1 : r.format == "rg8unorm" || r.format == "rg16unorm" ? s = 2 : s = await this.#T(r);
|
|
841
901
|
else {
|
|
842
|
-
const
|
|
843
|
-
|
|
902
|
+
const n = Z(r);
|
|
903
|
+
s = this.#R(n);
|
|
844
904
|
}
|
|
845
|
-
if (
|
|
846
|
-
if (this.#t(
|
|
847
|
-
if (this.#t(
|
|
848
|
-
} else if (
|
|
849
|
-
if (this.#t(
|
|
850
|
-
if (this.#t(
|
|
851
|
-
if (this.#t(
|
|
852
|
-
if (this.#t(
|
|
853
|
-
} else if (
|
|
854
|
-
if (this.#t(
|
|
855
|
-
if (this.#t(
|
|
856
|
-
} else if (
|
|
857
|
-
if (this.#t(
|
|
858
|
-
if (this.#t(
|
|
905
|
+
if (s == 4) {
|
|
906
|
+
if (this.#t(i.BC7_RGBA)) return i.BC7_RGBA;
|
|
907
|
+
if (this.#t(i.ASTC_4x4_RGBA)) return i.ASTC_4x4_RGBA;
|
|
908
|
+
} else if (s == 3) {
|
|
909
|
+
if (this.#t(i.BC7_RGB)) return i.BC7_RGB;
|
|
910
|
+
if (this.#t(i.ASTC_4x4_RGB)) return i.ASTC_4x4_RGB;
|
|
911
|
+
if (this.#t(i.BC1_RGB)) return i.BC1_RGB;
|
|
912
|
+
if (this.#t(i.ETC2_RGB)) return i.ETC2_RGB;
|
|
913
|
+
} else if (s == 2) {
|
|
914
|
+
if (this.#t(i.BC5_RG)) return i.BC5_RG;
|
|
915
|
+
if (this.#t(i.EAC_RG)) return i.EAC_RG;
|
|
916
|
+
} else if (s == 1) {
|
|
917
|
+
if (this.#t(i.BC4_R)) return i.BC4_R;
|
|
918
|
+
if (this.#t(i.EAC_R)) return i.EAC_R;
|
|
859
919
|
}
|
|
860
920
|
}
|
|
861
921
|
throw new Error("No supported format found.");
|
|
862
922
|
}
|
|
863
|
-
const t = this.#
|
|
923
|
+
const t = this.#b(e.format, e.preferLowQuality);
|
|
864
924
|
if (t === void 0)
|
|
865
925
|
throw new Error(`Unsupported format: ${e.format}`);
|
|
866
926
|
return t;
|
|
867
927
|
}
|
|
868
|
-
#
|
|
869
|
-
let r = !0, t = !0,
|
|
870
|
-
const
|
|
871
|
-
for (let
|
|
872
|
-
const
|
|
873
|
-
e[
|
|
874
|
-
const
|
|
875
|
-
(Math.abs(
|
|
928
|
+
#R(e) {
|
|
929
|
+
let r = !0, t = !0, s = 0;
|
|
930
|
+
const n = Math.min(1024 * 128, e.length);
|
|
931
|
+
for (let a = 0; a < n; a += 4) {
|
|
932
|
+
const o = e[a] / 255, c = e[a + 1] / 255, l = e[a + 2] / 255;
|
|
933
|
+
e[a + 3] < 255 && (r = !1), (o != c || c != l) && (t = !1);
|
|
934
|
+
const h = 2 * o - 1, m = 2 * c - 1, b = 2 * l - 1, _ = h * h + m * m + b * b, B = Math.sqrt(_);
|
|
935
|
+
(Math.abs(B - 1) > 0.2 || b < -0.1) && (s += 1);
|
|
876
936
|
}
|
|
877
|
-
return r ? t ? 1 : 16 *
|
|
937
|
+
return r ? t ? 1 : 16 * s < n ? 2 : 3 : 4;
|
|
878
938
|
}
|
|
879
|
-
async #
|
|
939
|
+
async #T(e) {
|
|
880
940
|
const t = this.#e.createBuffer({
|
|
881
941
|
size: 12,
|
|
882
942
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
883
|
-
}),
|
|
943
|
+
}), s = this.#e.createBuffer({
|
|
884
944
|
size: 12,
|
|
885
945
|
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
886
|
-
}),
|
|
887
|
-
layout: this.#
|
|
946
|
+
}), n = this.#e.createBindGroup({
|
|
947
|
+
layout: this.#m.getBindGroupLayout(0),
|
|
888
948
|
entries: [
|
|
889
949
|
{ binding: 0, resource: e.createView() },
|
|
890
950
|
{ binding: 1, resource: { buffer: t } }
|
|
891
951
|
]
|
|
892
|
-
}),
|
|
893
|
-
|
|
894
|
-
const { width:
|
|
895
|
-
|
|
896
|
-
const m = new Uint32Array(
|
|
897
|
-
return
|
|
952
|
+
}), a = this.#e.createCommandEncoder(), o = a.beginComputePass();
|
|
953
|
+
o.setPipeline(this.#m), o.setBindGroup(0, n);
|
|
954
|
+
const { width: c, height: l } = e, f = Math.ceil(c / 8), h = Math.ceil(l / 8);
|
|
955
|
+
o.dispatchWorkgroups(f, h), o.end(), a.copyBufferToBuffer(t, 0, s, 0, 12), this.#e.queue.submit([a.finish()]), await this.#e.queue.onSubmittedWorkDone(), await s.mapAsync(GPUMapMode.READ);
|
|
956
|
+
const m = new Uint32Array(s.getMappedRange()), b = m[0] == 0, _ = m[1] == 0, B = m[2];
|
|
957
|
+
return s.unmap(), s.destroy(), t.destroy(), b ? _ ? 1 : 4 * B < c * l ? 2 : 3 : 4;
|
|
898
958
|
}
|
|
899
959
|
// Apply scaling and flipY transform.
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
960
|
+
#_(e, r, t, s, n, a, o) {
|
|
961
|
+
if (this.#a) {
|
|
962
|
+
this.#P(e, r, t, s, n, a, o);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const c = e.beginComputePass(), l = o ? this.#u : this.#o;
|
|
966
|
+
c.setPipeline(l);
|
|
967
|
+
const f = this.#e.createBindGroup({
|
|
968
|
+
layout: l.getBindGroupLayout(0),
|
|
905
969
|
entries: [
|
|
906
970
|
{
|
|
907
971
|
binding: 0,
|
|
908
972
|
resource: r.createView({
|
|
909
973
|
baseMipLevel: 0,
|
|
910
974
|
mipLevelCount: 1,
|
|
911
|
-
format:
|
|
975
|
+
format: a == 1 ? "rgba8unorm-srgb" : "rgba8unorm",
|
|
912
976
|
usage: GPUTextureUsage.TEXTURE_BINDING
|
|
913
977
|
})
|
|
914
978
|
},
|
|
@@ -924,41 +988,89 @@ class L {
|
|
|
924
988
|
},
|
|
925
989
|
{
|
|
926
990
|
binding: 2,
|
|
927
|
-
resource: this.#
|
|
991
|
+
resource: this.#i
|
|
928
992
|
},
|
|
929
993
|
{
|
|
930
994
|
binding: 3,
|
|
931
|
-
resource: { buffer: this.#n[
|
|
995
|
+
resource: { buffer: this.#n[a] }
|
|
932
996
|
}
|
|
933
997
|
]
|
|
934
998
|
});
|
|
935
|
-
|
|
999
|
+
c.setBindGroup(0, f), c.dispatchWorkgroups(Math.ceil(s / 8), Math.ceil(n / 8)), c.end();
|
|
936
1000
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
c.
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1001
|
+
// Apply scaling and flipY transform.
|
|
1002
|
+
#P(e, r, t, s, n, a, o) {
|
|
1003
|
+
const c = a == 1 ? "rgba8unorm-srgb" : "rgba8unorm", l = t.createView({
|
|
1004
|
+
baseMipLevel: 0,
|
|
1005
|
+
mipLevelCount: 1,
|
|
1006
|
+
dimension: "2d",
|
|
1007
|
+
format: c,
|
|
1008
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
1009
|
+
}), f = e.beginRenderPass({
|
|
1010
|
+
colorAttachments: [
|
|
1011
|
+
{
|
|
1012
|
+
view: l,
|
|
1013
|
+
loadOp: "clear",
|
|
1014
|
+
storeOp: "store",
|
|
1015
|
+
clearValue: [0, 0, 0, 0]
|
|
1016
|
+
}
|
|
1017
|
+
]
|
|
1018
|
+
}), h = o ? this.#u[c] : this.#o[c];
|
|
1019
|
+
f.setPipeline(h);
|
|
1020
|
+
const m = this.#e.createBindGroup({
|
|
1021
|
+
layout: h.getBindGroupLayout(0),
|
|
1022
|
+
entries: [
|
|
1023
|
+
{
|
|
1024
|
+
binding: 0,
|
|
1025
|
+
resource: r.createView({
|
|
1026
|
+
baseMipLevel: 0,
|
|
1027
|
+
mipLevelCount: 1,
|
|
1028
|
+
format: a == 1 ? "rgba8unorm-srgb" : "rgba8unorm",
|
|
1029
|
+
usage: GPUTextureUsage.TEXTURE_BINDING
|
|
1030
|
+
})
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
binding: 2,
|
|
1034
|
+
resource: this.#i
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
binding: 3,
|
|
1038
|
+
resource: { buffer: this.#n[a] }
|
|
1039
|
+
}
|
|
1040
|
+
]
|
|
1041
|
+
});
|
|
1042
|
+
f.setBindGroup(0, m), f.draw(4, 1, 0, 0), f.end();
|
|
1043
|
+
}
|
|
1044
|
+
async #w(e, r, t, s, n, a) {
|
|
1045
|
+
let o = s, c = n;
|
|
1046
|
+
if (this.#a)
|
|
1047
|
+
for (let l = 0; l < t - 1; l++)
|
|
1048
|
+
o = Math.max(1, Math.floor(o / 2)), c = Math.max(1, Math.floor(c / 2)), this.#y(e, r, l, l + 1, o, c, a);
|
|
1049
|
+
else {
|
|
1050
|
+
const l = e.beginComputePass();
|
|
1051
|
+
l.setPipeline(this.#s);
|
|
1052
|
+
for (let f = 0; f < t - 1; f++)
|
|
1053
|
+
o = Math.max(1, Math.floor(o / 2)), c = Math.max(1, Math.floor(c / 2)), this.#x(l, r, f, f + 1, o, c, a);
|
|
1054
|
+
l.end();
|
|
1055
|
+
}
|
|
944
1056
|
}
|
|
945
|
-
#
|
|
946
|
-
const
|
|
947
|
-
layout: this.#
|
|
1057
|
+
#x(e, r, t, s, n, a, o) {
|
|
1058
|
+
const c = this.#e.createBindGroup({
|
|
1059
|
+
layout: this.#s.getBindGroupLayout(0),
|
|
948
1060
|
entries: [
|
|
949
1061
|
{
|
|
950
1062
|
binding: 0,
|
|
951
1063
|
resource: r.createView({
|
|
952
1064
|
baseMipLevel: t,
|
|
953
1065
|
mipLevelCount: 1,
|
|
954
|
-
format:
|
|
1066
|
+
format: o == 1 ? "rgba8unorm-srgb" : "rgba8unorm",
|
|
955
1067
|
usage: GPUTextureUsage.TEXTURE_BINDING
|
|
956
1068
|
})
|
|
957
1069
|
},
|
|
958
1070
|
{
|
|
959
1071
|
binding: 1,
|
|
960
1072
|
resource: r.createView({
|
|
961
|
-
baseMipLevel:
|
|
1073
|
+
baseMipLevel: s,
|
|
962
1074
|
mipLevelCount: 1,
|
|
963
1075
|
dimension: "2d",
|
|
964
1076
|
format: "rgba8unorm",
|
|
@@ -967,17 +1079,57 @@ class L {
|
|
|
967
1079
|
},
|
|
968
1080
|
{
|
|
969
1081
|
binding: 2,
|
|
970
|
-
resource: this.#
|
|
1082
|
+
resource: this.#i
|
|
971
1083
|
},
|
|
972
1084
|
{
|
|
973
1085
|
binding: 3,
|
|
974
|
-
resource: { buffer: this.#n[
|
|
1086
|
+
resource: { buffer: this.#n[o] }
|
|
1087
|
+
}
|
|
1088
|
+
]
|
|
1089
|
+
});
|
|
1090
|
+
e.setBindGroup(0, c), e.dispatchWorkgroups(Math.ceil(n / 8), Math.ceil(a / 8));
|
|
1091
|
+
}
|
|
1092
|
+
#y(e, r, t, s, n, a, o) {
|
|
1093
|
+
const c = o == 1 ? "rgba8unorm-srgb" : "rgba8unorm", l = r.createView({
|
|
1094
|
+
baseMipLevel: s,
|
|
1095
|
+
mipLevelCount: 1,
|
|
1096
|
+
dimension: "2d",
|
|
1097
|
+
format: c,
|
|
1098
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
1099
|
+
}), f = e.beginRenderPass({
|
|
1100
|
+
colorAttachments: [
|
|
1101
|
+
{
|
|
1102
|
+
view: l,
|
|
1103
|
+
loadOp: "clear",
|
|
1104
|
+
storeOp: "store",
|
|
1105
|
+
clearValue: [0, 0, 0, 0]
|
|
1106
|
+
}
|
|
1107
|
+
]
|
|
1108
|
+
}), h = this.#e.createBindGroup({
|
|
1109
|
+
layout: this.#s[c].getBindGroupLayout(0),
|
|
1110
|
+
entries: [
|
|
1111
|
+
{
|
|
1112
|
+
binding: 0,
|
|
1113
|
+
resource: r.createView({
|
|
1114
|
+
baseMipLevel: t,
|
|
1115
|
+
mipLevelCount: 1,
|
|
1116
|
+
format: c,
|
|
1117
|
+
usage: GPUTextureUsage.TEXTURE_BINDING
|
|
1118
|
+
})
|
|
1119
|
+
},
|
|
1120
|
+
{
|
|
1121
|
+
binding: 2,
|
|
1122
|
+
resource: this.#i
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
binding: 3,
|
|
1126
|
+
resource: { buffer: this.#n[o] }
|
|
975
1127
|
}
|
|
976
1128
|
]
|
|
977
1129
|
});
|
|
978
|
-
|
|
1130
|
+
f.setPipeline(this.#s[c]), f.setBindGroup(0, h), f.draw(4, 1, 0, 0), f.end();
|
|
979
1131
|
}
|
|
980
1132
|
}
|
|
981
1133
|
export {
|
|
982
|
-
|
|
1134
|
+
D as Spark
|
|
983
1135
|
};
|
|
@@ -2,6 +2,10 @@ const n = `struct Params {
|
|
|
2
2
|
colorMode: u32,
|
|
3
3
|
};
|
|
4
4
|
|
|
5
|
+
const COLOR_LINEAR : u32 = 0u;
|
|
6
|
+
const COLOR_SRGB : u32 = 1u;
|
|
7
|
+
const COLOR_NORMAL : u32 = 2u;
|
|
8
|
+
|
|
5
9
|
@group(0) @binding(0) var src : texture_2d<f32>;
|
|
6
10
|
@group(0) @binding(1) var dst : texture_storage_2d<rgba8unorm, write>;
|
|
7
11
|
@group(0) @binding(2) var smp: sampler;
|
|
@@ -38,25 +42,53 @@ fn mipmap(@builtin(global_invocation_id) id : vec3<u32>) {
|
|
|
38
42
|
|
|
39
43
|
let size_rcp = vec2f(1.0) / vec2f(dstSize);
|
|
40
44
|
|
|
41
|
-
// We
|
|
42
|
-
//
|
|
45
|
+
// We take 4 samples explicitly in order to support alpha weighting and for slightly more correct
|
|
46
|
+
// results when using non multiple of two textures.
|
|
43
47
|
let uv0 = (vec2f(id.xy) + vec2f(0.25)) * size_rcp;
|
|
44
48
|
let uv1 = uv0 + 0.5 * size_rcp;
|
|
45
49
|
|
|
46
50
|
var color = vec4f(0.0);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
if (params.colorMode == COLOR_SRGB) {
|
|
53
|
+
let c00 = textureSampleLevel(src, smp, vec2f(uv0.x, uv0.y), 0);
|
|
54
|
+
let c10 = textureSampleLevel(src, smp, vec2f(uv1.x, uv0.y), 0);
|
|
55
|
+
let c01 = textureSampleLevel(src, smp, vec2f(uv0.x, uv1.y), 0);
|
|
56
|
+
let c11 = textureSampleLevel(src, smp, vec2f(uv1.x, uv1.y), 0);
|
|
57
|
+
|
|
58
|
+
let a00 = c00.a;
|
|
59
|
+
let a10 = c10.a;
|
|
60
|
+
let a01 = c01.a;
|
|
61
|
+
let a11 = c11.a;
|
|
62
|
+
let a_sum = a00 + a10 + a01 + a11;
|
|
63
|
+
|
|
64
|
+
color.a = 0.25 * a_sum;
|
|
65
|
+
if (a_sum > 1.0 / 256.0) {
|
|
66
|
+
color.r = (c00.r * a00 + c10.r * a10 + c01.r * a01 + c11.r * a11) / a_sum;
|
|
67
|
+
color.g = (c00.g * a00 + c10.g * a10 + c01.g * a01 + c11.g * a11) / a_sum;
|
|
68
|
+
color.b = (c00.b * a00 + c10.b * a10 + c01.b * a01 + c11.b * a11) / a_sum;
|
|
69
|
+
} else {
|
|
70
|
+
color.r = 0.25 * (c00.r + c10.r + c01.r + c11.r);
|
|
71
|
+
color.g = 0.25 * (c00.g + c10.g + c01.g + c11.g);
|
|
72
|
+
color.b = 0.25 * (c00.b + c10.b + c01.b + c11.b);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// For linear colors, we assume no alpha.
|
|
77
|
+
// @@ We could normalize/reconstruct normals before averaging.
|
|
78
|
+
color += textureSampleLevel(src, smp, vec2f(uv0.x, uv0.y), 0);
|
|
79
|
+
color += textureSampleLevel(src, smp, vec2f(uv1.x, uv0.y), 0);
|
|
80
|
+
color += textureSampleLevel(src, smp, vec2f(uv0.x, uv1.y), 0);
|
|
81
|
+
color += textureSampleLevel(src, smp, vec2f(uv1.x, uv1.y), 0);
|
|
82
|
+
color *= 0.25;
|
|
83
|
+
}
|
|
52
84
|
|
|
53
85
|
// This would be the single sample implementation:
|
|
54
86
|
// let uv = (vec2f(id.xy) + vec2f(0.5)) * size_rcp;
|
|
55
87
|
// var color = textureSampleLevel(src, smp, vec2f(uv.x, uv.y), 0);
|
|
56
88
|
|
|
57
|
-
if (params.colorMode ==
|
|
89
|
+
if (params.colorMode == COLOR_SRGB) {
|
|
58
90
|
color = linear_to_srgb_vec4(color);
|
|
59
|
-
} else if (params.colorMode ==
|
|
91
|
+
} else if (params.colorMode == COLOR_NORMAL) {
|
|
60
92
|
color = normalize_vec4(color);
|
|
61
93
|
}
|
|
62
94
|
|
|
@@ -73,9 +105,9 @@ fn resize(@builtin(global_invocation_id) id : vec3<u32>) {
|
|
|
73
105
|
let uv = (vec2f(id.xy) + vec2f(0.5)) / vec2f(dstSize);
|
|
74
106
|
var color = textureSampleLevel(src, smp, uv, 0);
|
|
75
107
|
|
|
76
|
-
if (params.colorMode ==
|
|
108
|
+
if (params.colorMode == COLOR_SRGB) {
|
|
77
109
|
color = linear_to_srgb_vec4(color);
|
|
78
|
-
} else if (params.colorMode ==
|
|
110
|
+
} else if (params.colorMode == COLOR_NORMAL) {
|
|
79
111
|
color = normalize_vec4(color);
|
|
80
112
|
}
|
|
81
113
|
|
|
@@ -92,15 +124,80 @@ fn flipy(@builtin(global_invocation_id) id : vec3<u32>) {
|
|
|
92
124
|
let uv = (vec2f(f32(id.x), f32(dstSize.y - 1u - id.y)) + vec2f(0.5)) / vec2f(dstSize);
|
|
93
125
|
var color = textureSampleLevel(src, smp, uv, 0);
|
|
94
126
|
|
|
95
|
-
if (params.colorMode ==
|
|
127
|
+
if (params.colorMode == COLOR_SRGB) {
|
|
96
128
|
color = linear_to_srgb_vec4(color);
|
|
97
|
-
} else if (params.colorMode ==
|
|
129
|
+
} else if (params.colorMode == COLOR_NORMAL) {
|
|
98
130
|
color = normalize_vec4(color);
|
|
99
131
|
}
|
|
100
132
|
|
|
101
133
|
textureStore(dst, id.xy, color);
|
|
102
134
|
}
|
|
103
135
|
|
|
136
|
+
// Fullscreen vertex shader
|
|
137
|
+
struct VSOutput {
|
|
138
|
+
@builtin(position) pos: vec4<f32>,
|
|
139
|
+
@location(0) tex : vec2<f32>
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
@vertex
|
|
143
|
+
fn fullscreen_vs(@builtin(vertex_index) vertexIndex : u32) -> VSOutput {
|
|
144
|
+
|
|
145
|
+
var pos = array<vec2<f32>, 4>(
|
|
146
|
+
vec2<f32>(-1.0, 1.0),
|
|
147
|
+
vec2<f32>( 1.0, 1.0),
|
|
148
|
+
vec2<f32>(-1.0, -1.0),
|
|
149
|
+
vec2<f32>( 1.0, -1.0)
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
var tex = array<vec2<f32>, 4>(
|
|
153
|
+
vec2<f32>(0.0, 0.0),
|
|
154
|
+
vec2<f32>(1.0, 0.0),
|
|
155
|
+
vec2<f32>(0.0, 1.0),
|
|
156
|
+
vec2<f32>(1.0, 1.0)
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
var vs_output : VSOutput;
|
|
160
|
+
vs_output.tex = tex[vertexIndex];
|
|
161
|
+
vs_output.pos = vec4<f32>(pos[vertexIndex], 0.0, 1.0);
|
|
162
|
+
return vs_output;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@fragment
|
|
166
|
+
fn mipmap_fs(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
|
|
167
|
+
|
|
168
|
+
var color = textureSample(src, smp, uv);
|
|
169
|
+
|
|
170
|
+
if (params.colorMode == 2) {
|
|
171
|
+
color = normalize_vec4(color);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return color;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@fragment
|
|
178
|
+
fn resize_fs(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
|
|
179
|
+
|
|
180
|
+
var color = textureSample(src, smp, uv);
|
|
181
|
+
|
|
182
|
+
if (params.colorMode == 2) {
|
|
183
|
+
color = normalize_vec4(color);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return color;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@fragment
|
|
190
|
+
fn flipy_fs(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
|
|
191
|
+
|
|
192
|
+
var color = textureSample(src, smp, vec2(uv.x, 1 - uv.y));
|
|
193
|
+
|
|
194
|
+
if (params.colorMode == 2) {
|
|
195
|
+
color = normalize_vec4(color);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return color;
|
|
199
|
+
}
|
|
200
|
+
|
|
104
201
|
|
|
105
202
|
@group(0) @binding(1) var<storage, read_write> global_counters: array<atomic<u32>, 3>;
|
|
106
203
|
|