@ludicon/spark.js 0.0.13 → 0.0.14

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