import { ab as g, as as $, at as K, e as D, v as _, au as O, N as x, av as Z, a5 as W, aw as F, ax as j, ay as X, az as J, af as ee, a9 as k } from "./index-DSGwv2Yx.js";
import { m as te, f as se, P as re } from "./webgpu_program-CbjdYLYk.js";
import { i as ne, G as N } from "./webgpu_util-DuofJBMo.js";
import { m as q } from "./complex_util-Yc1A_gV1.js";
const d = g();
d.registerFlag("WEBGPU_DEFERRED_SUBMIT_BATCH_SIZE", () => 15);
d.registerFlag("WEBGPU_CPU_FORWARD", () => !0);
d.registerFlag("WEBGPU_MATMUL_PROGRAM_TYPE", () => -1);
d.registerFlag("WEBGPU_USE_NAIVE_CONV2D_TRANSPOSE", () => !0);
d.registerFlag("WEBGPU_USE_LOW_POWER_GPU", () => !1);
d.registerFlag("WEBGPU_CPU_HANDOFF_SIZE_THRESHOLD", () => 1e3);
d.registerFlag("WEBGPU_USE_PROFILE_TOOL", () => !1);
d.registerFlag("WEBGPU_IMPORT_EXTERNAL_TEXTURE", () => !0);
d.registerFlag("WEBGPU_USE_NAIVE_CONV2D_DEBUG", () => !1);
d.registerFlag("WEBGPU_THRESHOLD_TO_INCREASE_WORKGROUPS_FOR_MATMUL", () => -1);
d.registerFlag("WEBGPU_CONV_SEPARATE_IM2COL_SHADER", () => !1);
d.registerFlag("WEBGPU_PRINT_SHADER", () => "");
d.registerFlag("WEBGPU_ENGINE_COMPILE_ONLY", () => !1);
class ae {
  constructor(e) {
    e && (this.vendor = e.vendor, this.architecture = e.architecture, this.intelGPUGeneration = this.getIntelGPUGeneration());
  }
  getIntelGPUGeneration() {
    if (this.isIntel()) {
      if (this.architecture.startsWith("gen"))
        return Number(this.architecture.match(/\d+/));
      if (this.architecture.startsWith("xe"))
        return 12;
    }
    return 0;
  }
  isIntel() {
    return this.vendor === "intel";
  }
}
class ie {
  constructor(e) {
    this.device = e, this.numUsedBuffers = 0, this.numFreeBuffers = 0, this.freeBuffers = /* @__PURE__ */ new Map(), this.usedBuffers = /* @__PURE__ */ new Map(), this.numBytesUsed = 0, this.numBytesAllocated = 0;
  }
  acquireBuffer(e, t, s = !1, n = !0) {
    let r;
    const a = z(e, t);
    return n ? (this.freeBuffers.has(a) || this.freeBuffers.set(a, []), this.freeBuffers.get(a).length > 0 ? (r = this.freeBuffers.get(a).pop(), this.numFreeBuffers--) : (r = this.device.createBuffer({ size: e, usage: t, mappedAtCreation: s }), this.numBytesAllocated += e)) : (r = this.device.createBuffer({ size: e, usage: t, mappedAtCreation: s }), this.numBytesAllocated += e), this.usedBuffers.has(a) || this.usedBuffers.set(a, []), this.usedBuffers.get(a).push(r), this.numUsedBuffers++, this.numBytesUsed += e, r;
  }
  releaseBuffer(e, t = !0) {
    if (this.freeBuffers.size === 0)
      return;
    const s = e.size, n = e.usage, r = z(s, n), a = this.usedBuffers.get(r), i = a.indexOf(e);
    if (i < 0)
      throw new Error("Cannot find the buffer in buffer manager");
    a[i] = a[a.length - 1], a.pop(), this.numUsedBuffers--, this.numBytesUsed -= s, t ? (this.freeBuffers.get(r).push(e), this.numFreeBuffers++) : (e.destroy(), this.numBytesAllocated -= s);
  }
  getNumUsedBuffers() {
    return this.numUsedBuffers;
  }
  getNumFreeBuffers() {
    return this.numFreeBuffers;
  }
  dispose() {
    this.freeBuffers.forEach((e, t) => {
      e.forEach((s) => {
        s.destroy();
      });
    }), this.usedBuffers.forEach((e, t) => {
      e.forEach((s) => {
        s.destroy();
      });
    }), this.freeBuffers = /* @__PURE__ */ new Map(), this.usedBuffers = /* @__PURE__ */ new Map(), this.numUsedBuffers = 0, this.numFreeBuffers = 0, this.numBytesUsed = 0, this.numBytesAllocated = 0;
  }
}
function z(l, e) {
  return `${l}_${e}`;
}
class oe {
  constructor(e) {
    this.device = e, this.numUsedTextures = 0, this.numFreeTextures = 0, this.freeTextures = /* @__PURE__ */ new Map(), this.usedTextures = /* @__PURE__ */ new Map(), this.numBytesUsed = 0, this.numBytesAllocated = 0;
  }
  acquireTexture(e, t, s, n) {
    const r = Q(s), a = e * t * r, i = L(e, t, s, n);
    if (this.freeTextures.has(i) || this.freeTextures.set(i, []), this.usedTextures.has(i) || this.usedTextures.set(i, []), this.numBytesUsed += a, this.numUsedTextures++, this.freeTextures.get(i).length > 0) {
      this.numFreeTextures--;
      const o = this.freeTextures.get(i).shift();
      return this.usedTextures.get(i).push(o), o;
    }
    this.numBytesAllocated += a;
    const u = this.device.createTexture({
      size: [e, t],
      format: s,
      usage: n
    });
    return this.usedTextures.get(i).push(u), u;
  }
  releaseTexture(e) {
    if (this.freeTextures.size === 0)
      return;
    const t = e.width, s = e.height, n = e.format, r = e.usage, a = L(t, s, n, r);
    this.freeTextures.has(a) || this.freeTextures.set(a, []), this.freeTextures.get(a).push(e), this.numFreeTextures++, this.numUsedTextures--;
    const i = this.usedTextures.get(a), u = i.indexOf(e);
    if (u < 0)
      throw new Error("Cannot release a texture that was never provided by this texture manager");
    i.splice(u, 1);
    const o = Q(n), f = t * s * o;
    this.numBytesUsed -= f;
  }
  getNumUsedTextures() {
    return this.numUsedTextures;
  }
  getNumFreeTextures() {
    return this.numFreeTextures;
  }
  dispose() {
    this.freeTextures.forEach((e, t) => {
      e.forEach((s) => {
        s.destroy();
      });
    }), this.usedTextures.forEach((e, t) => {
      e.forEach((s) => {
        s.destroy();
      });
    }), this.freeTextures = /* @__PURE__ */ new Map(), this.usedTextures = /* @__PURE__ */ new Map(), this.numUsedTextures = 0, this.numFreeTextures = 0, this.numBytesUsed = 0, this.numBytesAllocated = 0;
  }
}
function L(l, e, t, s) {
  return `${l}_${e}_${t}_${s}`;
}
function Q(l) {
  if (l === "rgba8unorm")
    return 16;
  throw new Error(`${l} is not supported!`);
}
const ue = g().getNumber("WEBGPU_CPU_HANDOFF_SIZE_THRESHOLD"), fe = (l, e) => {
  const t = l.limits.maxComputeWorkgroupsPerDimension, s = e.dispatchLayout, n = e.dispatch;
  if (n.every((a) => a <= t))
    return n;
  _(n[0] > t && s.y === void 0 && s.z === void 0, () => "Dispatch size exceeds WebGPU limits in Y or Z dimension.");
  let r = Math.ceil(Math.sqrt(n[0]));
  return r > t ? (r = Math.ceil(Math.cbrt(n[0])), _(r <= t, () => "Total dispatch size exceeds WebGPU maximum."), [r, r, r]) : [r, r, 1];
};
class R extends $ {
  nextDataId() {
    return R.nextDataId++;
  }
  constructor(e, t) {
    if (super(), this.commandQueueOwnedIds = /* @__PURE__ */ new WeakSet(), this.dispatchCountInPass = 0, this.disposed = !1, this.downloadWaitMs = 0, this.tensorDataPendingDisposal = [], this.queryResolveBuffer = null, this.querySet = null, this.querySetCount = 2, this.stagingPendingDisposal = [], this.uniformPendingDisposal = [], this.uploadWaitMs = 0, this.hasReadSyncWarned = !1, this.hasTimestampQueryWarned = !1, !ne())
      throw new Error("WebGPU is not supported on this device");
    this.pipelineCache = {}, this.device = e, this.queue = e.queue, this.commandEncoder = null, this.computePassEncoder = null, this.adapterInfo = new ae(t), this.supportTimestampQuery = this.device.features.has("timestamp-query"), this.thresholdToIncreaseWorkgroups = this.adapterInfo.intelGPUGeneration >= 12 ? 16 : 8, this.bufferManager = new ie(this.device), this.textureManager = new oe(this.device), this.tensorMap = new K(this, D()), g().getBool("WEBGPU_USE_PROFILE_TOOL") && (this.dummyCanvas = document.createElement("canvas"), this.dummyCanvas.width = 1, this.dummyCanvas.height = 1, this.dummyContext = this.dummyCanvas.getContext("webgpu"), this.dummyContext.configure({
      device: e,
      format: "bgra8unorm"
    }), document.body.appendChild(this.dummyCanvas));
  }
  floatPrecision() {
    return 32;
  }
  /**
   * Dispose the memory if the dataId has 0 refCount. Return true if the memory
   * is released or delayed in this backend, false if there are still
   * references.
   * @param dataId
   * @oaram force Optional, remove the data regardless of refCount
   */
  disposeData(e, t = !1) {
    if (!this.tensorMap.has(e))
      return !0;
    const s = this.tensorMap.get(e);
    return t ? s.refCount = 0 : s.refCount--, s.refCount > 0 ? !1 : (s.complexTensorInfos != null && (this.disposeData(s.complexTensorInfos.real.dataId), this.disposeData(s.complexTensorInfos.imag.dataId)), this.commandQueueOwnedIds.has(e) ? (this.tensorDataPendingDisposal.push(e), !0) : (this.releaseResource(e), this.tensorMap.delete(e), !0));
  }
  memory() {
    return {
      numBytesInGPU: this.bufferManager.numBytesUsed,
      numBytesAllocatedInGPU: this.bufferManager.numBytesAllocated,
      unreliable: !1
    };
  }
  releaseResource(e) {
    const t = this.tensorMap.get(e);
    if (!(!t || !t.resource)) {
      if (t.external) {
        t.resource = null;
        return;
      }
      t.resource instanceof GPUBuffer ? this.bufferManager.releaseBuffer(t.resource) : t.resource instanceof GPUTexture && this.textureManager.releaseTexture(t.resource), t.resource = null;
    }
  }
  /** Return refCount of a `TensorData`. */
  refCount(e) {
    return this.tensorMap.has(e) ? this.tensorMap.get(e).refCount : 0;
  }
  /** Increase refCount of a `TensorData`. */
  incRef(e) {
    const t = this.tensorMap.get(e);
    t.refCount++;
  }
  /** Decrease refCount of a `TensorData`. */
  decRef(e) {
    if (this.tensorMap.has(e)) {
      const t = this.tensorMap.get(e);
      t.refCount--;
    }
  }
  write(e, t, s) {
    if (s === "complex64" && e != null)
      throw new Error("Cannot write to a complex64 dtype. Please use tf.complex(real, imag).");
    const n = { id: this.nextDataId() };
    return this.tensorMap.set(n, { dtype: s, shape: t, values: e, refCount: 1 }), n;
  }
  move(e, t, s, n, r) {
    if (n === "complex64")
      throw new Error("Cannot write to a complex64 dtype. Please use tf.complex(real, imag).");
    this.tensorMap.set(e, { dtype: n, shape: s, values: t, refCount: r });
  }
  submitQueue() {
    this.queue.submit([this.commandEncoder.finish()]), this.commandEncoder = null, this.dispatchCountInPass = 0, this.commandQueueOwnedIds = /* @__PURE__ */ new WeakSet(), this.tensorDataPendingDisposal.forEach((e) => {
      this.releaseResource(e), this.tensorMap.delete(e);
    }), this.uniformPendingDisposal.forEach((e) => this.bufferManager.releaseBuffer(e)), this.stagingPendingDisposal.forEach((e) => this.bufferManager.releaseBuffer(e, !1)), this.tensorDataPendingDisposal = [], this.uniformPendingDisposal = [], this.stagingPendingDisposal = [];
  }
  ensureCommandEncoderReady() {
    this.commandEncoder || (this.commandEncoder = this.device.createCommandEncoder());
  }
  endComputePassEncoder() {
    this.computePassEncoder && (this.computePassEncoder.end(), this.computePassEncoder = null);
  }
  // Check if parallel compilation is done.
  async checkCompileCompletionAsync() {
    let e;
    try {
      e = await Promise.all(Object.values(this.pipelineCache));
    } catch (t) {
      throw new Error(t.message);
    }
    Object.keys(this.pipelineCache).map((t, s) => {
      this.pipelineCache[t] = e[s];
    });
  }
  async getBufferData(e) {
    if (g().getBool("WEBGPU_ENGINE_COMPILE_ONLY"))
      return console.warn("The data may be invalid since WEBGPU_ENGINE_COMPILE_ONLY is true, this can only be called when WEBGPU_ENGINE_COMPILE_ONLY is false"), null;
    const t = e.size, s = this.bufferManager.acquireBuffer(t, GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ);
    this.ensureCommandEncoderReady(), this.endComputePassEncoder(), this.commandEncoder.copyBufferToBuffer(e, 0, s, 0, t), this.submitQueue(), await s.mapAsync(GPUMapMode.READ);
    const n = s.getMappedRange().slice(0);
    return s.unmap(), s != null && this.bufferManager.releaseBuffer(s), g().getBool("WEBGPU_USE_PROFILE_TOOL") && (_(this.dummyContext !== void 0, () => "Fail to get context for profiling tool"), this.dummyContext.getCurrentTexture()), n;
  }
  convertAndCacheOnCPU(e, t) {
    const s = this.tensorMap.get(e);
    return s.values = t, s.values;
  }
  readSync(e) {
    const t = this.tensorMap.get(e), { values: s, complexTensorInfos: n } = t;
    if (s != null || t.dtype === "string")
      return s;
    if (t.dtype === "complex64") {
      const E = this.readSync(n.real.dataId), B = this.readSync(n.imag.dataId), y = O(q(E, B).buffer, "float32");
      return this.convertAndCacheOnCPU(e, y), y;
    }
    this.hasReadSyncWarned || (this.hasReadSyncWarned = !0, console.warn("The performance of synchronously reading data from GPU to CPU is poor on the webgpu backend, please use asynchronous APIs instead."));
    const r = ["opaque", "premultiplied"], a = t.resource, i = a.size;
    _(i % 4 === 0, () => "Because there is 4 bytes for one pixel, buffer size must be multiple of 4.");
    const u = i / 4, o = new ArrayBuffer(i), f = 256, c = 256, h = r.map((E) => new OffscreenCanvas(f, c)), m = new OffscreenCanvas(f, c);
    this.endComputePassEncoder(), h.map((E, B) => {
      const y = E.getContext("webgpu");
      return y.configure({
        device: this.device,
        format: "bgra8unorm",
        usage: GPUTextureUsage.COPY_DST,
        alphaMode: r[B]
      }), y.getCurrentTexture();
    }).map((E, B) => {
      const y = f * 4, G = (P, S, v) => {
        this.ensureCommandEncoderReady(), this.commandEncoder.copyBufferToTexture({
          buffer: a,
          bytesPerRow: y,
          offset: v
        }, {
          texture: E
        }, {
          width: P,
          height: S
        }), this.submitQueue();
        const I = m.getContext("2d", {
          willReadFrequently: !0
        });
        I.clearRect(0, 0, P, S), I.drawImage(h[B], 0, 0);
        const b = I.getImageData(0, 0, P, S).data, H = r[B], M = new Uint8ClampedArray(o, v, P * S * 4);
        for (let p = 0; p < M.length; p += 4)
          if (H === "premultiplied")
            M[p + 3] = b[p + 3];
          else {
            const V = b[p];
            M[p] = b[p + 2], M[p + 1] = b[p + 1], M[p + 2] = V;
          }
      }, Y = Math.floor(u / (f * c));
      let T = f, U = c, C = 0;
      for (let P = 0; P < Y; P++)
        G(T, U, C), C += f * c * 4;
      const A = u % (f * c);
      U = Math.floor(A / f), U > 0 && (G(T, U, C), C += U * (f * 4)), T = A % f, T > 0 && G(T, 1, C);
    });
    const w = O(o, t.dtype);
    return this.convertAndCacheOnCPU(e, w), w;
  }
  async read(e) {
    if (!this.tensorMap.has(e))
      throw new Error(`Tensor ${e} was not registered!`);
    const t = this.tensorMap.get(e), { values: s } = t;
    if (s != null)
      return s;
    let n;
    if (t.dtype === "complex64") {
      const r = await Promise.all([
        this.read(t.complexTensorInfos.real.dataId),
        this.read(t.complexTensorInfos.imag.dataId)
      ]), a = r[0], i = r[1];
      n = q(a, i);
    } else {
      const r = await this.getBufferData(t.resource);
      n = O(r, t.dtype);
    }
    return this.convertAndCacheOnCPU(e, n), n;
  }
  // The source GPUBuffer and destination GPUBuffer have the same size and
  // usage.
  copyBuffer(e) {
    const t = e.size, s = e.usage, n = this.bufferManager.acquireBuffer(t, s);
    return this.ensureCommandEncoderReady(), this.endComputePassEncoder(), this.commandEncoder.copyBufferToBuffer(e, 0, n, 0, t), this.submitQueue(), n;
  }
  /**
   * Create a TF.js tensor out of an existing WebGPU buffer.
   */
  createTensorFromGPUData(e, t, s) {
    let n = e.buffer;
    if (s === "complex64")
      throw new Error("Cannot write to a complex64 dtype. ");
    const r = { id: this.nextDataId() };
    this.tensorMap.set(r, {
      dtype: s,
      shape: t,
      values: null,
      refCount: 1,
      external: e.zeroCopy
    });
    const a = this.tensorMap.get(r), i = N(a.dtype) * x(a.shape);
    if (e.buffer.size < i)
      throw new Error(`GPUBuffer size(${e.buffer.size}) is smaller than tensor size(${i})!`);
    if ((e.buffer.usage & (GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC)) !== (GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC))
      throw new Error("GPUBuffer.usage should include GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC!");
    return e.zeroCopy !== !0 && (n = this.copyBuffer(n)), a.resource = n, D().makeTensorFromDataId(r, t, s, this);
  }
  /**
   * Read tensor to a new GPUBuffer.
   * @param dataId The source tensor.
   */
  readToGPU(e) {
    const t = this.tensorMap.get(e), { values: s, dtype: n, shape: r, resource: a } = t;
    if (n === "complex64")
      throw new Error("Does not support reading buffer for complex64 dtype.");
    if (a == null)
      throw s != null ? new Error("Data is not on GPU but on CPU.") : new Error("There is no data on GPU or CPU.");
    const i = a, u = i.size, o = i.usage, f = this.bufferManager.acquireBuffer(u, o);
    this.ensureCommandEncoderReady(), this.endComputePassEncoder(), this.commandEncoder.copyBufferToBuffer(a, 0, f, 0, u), this.submitQueue();
    const c = this.makeTensorInfo(r, n), h = D().makeTensorFromTensorInfo(c), m = this.tensorMap.get(c.dataId);
    return m.resource = f, { tensorRef: h, buffer: f };
  }
  bufferSync(e) {
    const t = this.readSync(e.dataId);
    if (e.dtype === "string")
      try {
        const s = t.map((n) => Z(n));
        return W(e.shape, e.dtype, s);
      } catch {
        throw new Error("Failed to decode encoded string bytes into utf-8");
      }
    return W(e.shape, e.dtype, t);
  }
  async time(e) {
    !this.supportTimestampQuery && !this.hasTimestampQueryWarned && (console.warn("This device doesn't support timestamp-query extension. Start Chrome browser with flag --enable-dawn-features=allow_unsafe_apis to try it again. Otherwise, zero will be shown for the kernel time when profiling mode is enabled."), this.hasTimestampQueryWarned = !0);
    const t = this.activeTimers, s = [];
    let n = !1;
    this.programTimersStack == null ? (this.programTimersStack = s, n = !0) : this.activeTimers.push(s), this.activeTimers = s, e();
    const r = F(this.activeTimers.map((o) => o.query)).filter((o) => o != null), a = F(this.activeTimers.map((o) => o.name)).filter((o) => o != null);
    this.activeTimers = t, n && (this.programTimersStack = null);
    const i = {
      uploadWaitMs: this.uploadWaitMs,
      downloadWaitMs: this.downloadWaitMs,
      kernelMs: null,
      wallMs: null
    }, u = await Promise.all(r);
    return i.kernelMs = j(u), i.getExtraProfileInfo = () => u.map((o, f) => ({ name: a[f], ms: o })).map((o) => `${o.name}: ${o.ms}`).join(", "), this.uploadWaitMs = 0, this.downloadWaitMs = 0, i;
  }
  makeTensorInfo(e, t, s) {
    return t === "string" && s != null && s.length > 0 && X(s[0]) && (s = s.map((r) => J(r))), { dataId: this.write(s, e, t), shape: e, dtype: t };
  }
  tensorToBinding(e) {
    if (!e)
      return null;
    const s = this.tensorMap.get(e.dataId).resource;
    return s instanceof GPUBuffer ? { buffer: s } : s instanceof GPUTexture ? s.createView() : s;
  }
  uploadToGPU(e) {
    const t = this.tensorMap.get(e);
    if (t.resource != null)
      return;
    const s = N(t.dtype) * x(t.shape);
    let n;
    const r = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST;
    if (t.values) {
      if (n = this.bufferManager.acquireBuffer(s, r, !0), n.mapState === "unmapped") {
        const a = this.bufferManager.acquireBuffer(s, GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC, !0, !1), i = a.getMappedRange();
        t.dtype === "int32" || t.dtype === "packedF16" || t.dtype === "bool" ? new Int32Array(i).set(t.values) : new Float32Array(i).set(t.values), a.unmap(), this.ensureCommandEncoderReady(), this.endComputePassEncoder(), this.commandEncoder.copyBufferToBuffer(a, 0, n, 0, s), this.stagingPendingDisposal.push(a);
      } else {
        const a = n.getMappedRange();
        t.dtype === "int32" || t.dtype === "packedF16" || t.dtype === "bool" ? new Int32Array(a).set(t.values) : new Float32Array(a).set(t.values), n.unmap();
      }
      t.values = null;
    } else
      n = this.bufferManager.acquireBuffer(s, r);
    t.resource = n;
  }
  makeUniforms(e) {
    let t = 0, s = 0;
    const n = [];
    let r = 1;
    e.forEach((u) => {
      u.data.length === 0 && (u.data = [1]);
      let o;
      switch (u.data.length) {
        case 1:
          o = 4;
          break;
        case 2:
          o = 8;
          break;
        case 3:
          o = 16;
          break;
        case 4:
          o = 16;
          break;
        case 5:
          o = 16;
          break;
        case 6:
          o = 16;
          break;
        default:
          _(!1, () => `Unsupported ${u.data.length}D shape`);
      }
      (s === 5 || s === 6) && (o = 16), o > r && (r = o), t = Math.ceil(t / o) * o, s = u.data.length, n.push(t), t += u.data.length * 4;
    }), t = Math.ceil(t / r) * r;
    const a = new ArrayBuffer(t);
    e.forEach((u, o) => {
      const f = n[o];
      u.type === "int32" ? new Int32Array(a, f, u.data.length).set(u.data) : u.type === "uint32" ? new Uint32Array(a, f, u.data.length).set(u.data) : new Float32Array(a, f, u.data.length).set(u.data);
    });
    const i = this.bufferManager.acquireBuffer(t, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM);
    return this.queue.writeBuffer(i, 0, a, 0, t), this.uniformPendingDisposal.push(i), { offset: 0, size: t, buffer: i };
  }
  runWebGPUProgram(e, t, s, n, r) {
    if (r || (r = this.makeTensorInfo(e.outputShape, s)), x(r.shape) === 0)
      return this.tensorMap.get(r.dataId).values = ee(r.dtype, 0), r;
    this.uploadToGPU(r.dataId), e.dispatch = fe(this.device, e);
    const a = t.map((u, o) => {
      if (u.dtype === "complex64")
        throw new Error("GPGPUProgram does not support complex64 input. For complex64 dtypes, please separate the program into real and imaginary parts.");
      return this.uploadToGPU(u.dataId), {
        // Returning dtype from tensorMap because it reflects dtype
        // of underlying buffer, rather than abstract dtype.
        dtype: this.tensorMap.get(u.dataId).dtype,
        shape: u.shape,
        name: e.variableNames[o]
      };
    });
    e.shaderKey = te(e, a, r);
    const i = g().getBool("WEBGPU_ENGINE_COMPILE_ONLY");
    return e.shaderKey in this.pipelineCache || (this.pipelineCache[e.shaderKey] = se(this.device, e, a, r, i)), e.pipeline = this.pipelineCache[e.shaderKey], i || this.recordAndSubmit(e, r, t, n), r;
  }
  recordAndSubmit(e, t, s, n) {
    if (e.pipeline instanceof Promise)
      throw new Error("Please call checkCompileCompletionAsync to ensure parallel compilation is done!");
    let r = [], a = [];
    const i = "int32";
    if (e.pixelsOpType == null) {
      r.push({ type: "float32", data: [NaN] }, { type: "float32", data: [1 / 0] }), a = s.concat(t).map((m) => m.shape);
      const h = "int32";
      a.map((m) => {
        r.push({ type: h, data: m });
        const w = k(m);
        r.push({ type: h, data: w });
      });
    } else {
      const h = k(t.shape);
      r.push({ type: i, data: h });
    }
    if (e.size) {
      const h = x(e.outputShape);
      r.push({
        type: i,
        data: [e.outputComponent ? h / e.outputComponent : h]
      });
    }
    n && (r = [...r, ...n]);
    const u = [
      this.tensorToBinding(t),
      ...s.map((h) => this.tensorToBinding(h)),
      this.makeUniforms(r)
    ];
    s.forEach((h) => {
      this.commandQueueOwnedIds.add(h.dataId);
    }), this.commandQueueOwnedIds.add(t.dataId);
    const o = this.device.createBindGroup({
      layout: e.pipeline.getBindGroupLayout(0),
      entries: u.map((h, m) => ({ binding: m, resource: h }))
    }), f = this.activeTimers != null;
    this.ensureCommandEncoderReady();
    const c = {};
    f && this.supportTimestampQuery ? (this.endComputePassEncoder(), this.querySet == null && (this.querySet = this.device.createQuerySet({
      type: "timestamp",
      count: this.querySetCount
    })), c.timestampWrites = {
      querySet: this.querySet,
      beginningOfPassWriteIndex: 0,
      endOfPassWriteIndex: 1
    }, this.computePassEncoder = this.commandEncoder.beginComputePass(c)) : this.computePassEncoder || (this.computePassEncoder = this.commandEncoder.beginComputePass(c)), this.computePassEncoder.setPipeline(e.pipeline), this.computePassEncoder.setBindGroup(0, o), this.computePassEncoder.dispatchWorkgroups(e.dispatch[0], e.dispatch[1], e.dispatch[2]), this.dispatchCountInPass++, (f || g().get("WEBGPU_DEFERRED_SUBMIT_BATCH_SIZE") <= this.dispatchCountInPass || e.pixelsOpType === re.DRAW) && (this.endComputePassEncoder(), f ? this.activeTimers.push({ name: e.constructor.name, query: this.getQueryTime() }) : this.submitQueue());
  }
  async getQueryTime() {
    if (!this.supportTimestampQuery)
      return 0;
    this.queryResolveBuffer == null && (this.queryResolveBuffer = this.bufferManager.acquireBuffer(this.querySetCount * 8, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.QUERY_RESOLVE)), this.commandEncoder.resolveQuerySet(this.querySet, 0, this.querySetCount, this.queryResolveBuffer, 0);
    const e = this.bufferManager.acquireBuffer(this.querySetCount * 8, GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST);
    this.commandEncoder.copyBufferToBuffer(this.queryResolveBuffer, 0, e, 0, this.querySetCount * 8), this.submitQueue(), await e.mapAsync(GPUMapMode.READ);
    const t = new BigUint64Array(e.getMappedRange()), s = Number(t[1] - t[0]) / 1e6;
    return e.unmap(), this.bufferManager.releaseBuffer(e), s;
  }
  shouldExecuteOnCPU(e, t = ue) {
    return g().getBool("WEBGPU_CPU_FORWARD") && e.every((s) => this.tensorMap.get(s.dataId).resource == null && x(s.shape) < t);
  }
  numDataIds() {
    return this.tensorMap.numDataIds() - this.tensorDataPendingDisposal.length;
  }
  dispose() {
    this.disposed || (this.querySet != null && this.querySet.destroy(), this.bufferManager.dispose(), this.textureManager.dispose(), this.disposed = !0);
  }
}
R.nextDataId = 0;
export {
  R as W
};
