{"version":3,"sources":["/home/runner/work/webgpu-pipeline-kit/webgpu-pipeline-kit/dist/prod/index.cjs","../../src/builders.ts","../../src/utils/compare.ts","../../src/utils/array.ts","../../src/utils/Capacity.ts","../../src/utils/change-detector.ts","../../src/math/Color.ts","../../src/utils/math.ts","../../src/math/Quaternion.ts","../../src/math/Vector3.ts","../../src/math/Camera.ts","../../src/math/Transformation.ts","../../src/math/Vector2.ts","../../src/mesh-factories.ts","../../src/resources.ts","../../src/buffer-factory.ts","../../src/marshall.ts","../../src/buffer-resources.ts","../../src/pipeline-utils.ts","../../src/pipeline-resources.ts","../../src/types/peripheral-events.ts","../../src/pipeline.ts","../../src/peripheral-events.ts","../../src/pipeline-runner.ts","../../src/factories.ts"],"names":["buffer","WPKMouseButton"],"mappings":"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","file":"/home/runner/work/webgpu-pipeline-kit/webgpu-pipeline-kit/dist/prod/index.cjs","sourcesContent":[null,"import { fluentBuilder } from 'ts-fluent-builder';\n\nimport { WPKBufferFormat, WPKBufferFormatMap, WPKGroupBindingCompute, WPKGroupBindingRender, WPKMeshTemplateMap, WPKPipelineOptions, WPKRenderPassFragment, WPKRenderPassMesh, WPKRenderPassVertex, WPKComputeShader, WPKRenderShader, WPKVaryingsBufferFormat } from './types';\n\nconst bufferFormatBuilder = <TUniform, TEntity>() => fluentBuilder<WPKBufferFormat<TUniform, TEntity>>();\nconst computeGroupBindingsBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>() => fluentBuilder<Array<WPKGroupBindingCompute<TUniform, TEntity, TBufferFormatMap>>>();\nconst renderGroupBindingsBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>() => fluentBuilder<Array<WPKGroupBindingRender<TUniform, TEntity, TBufferFormatMap>>>();\nconst computeShaderBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>() => fluentBuilder<WPKComputeShader<TUniform, TEntity, TBufferFormatMap>>();\nconst meshTemplateBuilder = <TMeshTemplateMap extends WPKMeshTemplateMap>() => fluentBuilder<WPKRenderPassMesh<TMeshTemplateMap>>();\nconst vertexShaderBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TVaryings extends WPKVaryingsBufferFormat<TBufferFormatMap> | undefined = undefined>() => fluentBuilder<WPKRenderPassVertex<TUniform, TEntity, TBufferFormatMap, TVaryings>>();\nconst fragmentShaderBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TVaryings extends WPKVaryingsBufferFormat<TBufferFormatMap> | undefined = undefined>() => fluentBuilder<WPKRenderPassFragment<TUniform, TEntity, TBufferFormatMap, TVaryings>>();\nconst renderShaderBuilder = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMeshTemplateMap extends WPKMeshTemplateMap, TVaryings extends WPKVaryingsBufferFormat<TBufferFormatMap> | undefined = undefined>() => fluentBuilder<WPKRenderShader<TUniform, TEntity, TBufferFormatMap, TMeshTemplateMap, TVaryings>>();\nconst pipelineOptionsBuilder = <TUniform, TEntity, TMutableUniform extends boolean, TMutableEntities extends boolean, TResizeableEntities extends boolean>() => fluentBuilder<WPKPipelineOptions<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>>();\n\nexport const builders = {\n  bufferFormat: bufferFormatBuilder,\n  computeGroupBindings: computeGroupBindingsBuilder,\n  renderGroupBindings: renderGroupBindingsBuilder,\n  computeShader: computeShaderBuilder,\n  meshTemplate: meshTemplateBuilder,\n  vertexShader: vertexShaderBuilder,\n  fragmentShader: fragmentShaderBuilder,\n  renderShader: renderShaderBuilder,\n  pipelineOptions: pipelineOptionsBuilder,\n};\n","export type Comparator<T> = (a: T, b: T) => number;\nexport type Equality<T> = (a: T, b: T) => boolean;\n\nexport const equalityFactory = {\n  ofDoubleEquals: <T>(): Equality<T> => (a, b) => a == b,\n  ofTripleEquals: <T>(): Equality<T> => (a, b) => a === b,\n};\n","import { equalityFactory, Equality } from './compare';\nimport { Random } from './random';\n\nexport const arrayFuncs = {\n  equals: <T>(a: T[], b: T[], equality: Equality<T> = equalityFactory.ofTripleEquals()) => {\n    if (a.length !== b.length) {\n      return false;\n    }\n    return a.every((val, i) => equality(val, b[i]));\n  },\n  shuffle: <T>(array: T[], random: Random): T[] => {\n    const shuffled = [...array];\n    // last to first ensures fairness while keeping it simple\n    for (let i = shuffled.length - 1; i > 0; i--) {\n      const j = random.intMinMax(0, i);\n      [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];\n    }\n    return shuffled;\n  },\n  merge: <T>(...arrays: (T[] | undefined | null)[]): T[] => arrays.flatMap(arr => arr ?? []),\n  toRecord: <T, K extends string | number | symbol, V>(array: T[], toKey: (element: T) => K, toValue: (element: T) => V): Record<K, V> => {\n    return array.reduce((acc, element) => {\n      const key = toKey(element);\n      const value = toValue(element);\n      acc[key] = value;\n      return acc;\n    }, {} as Record<K, V>);\n  },\n  toMap: <T, K, V>(array: T[], toKey: (element: T, index: number) => K, toValue: (element: T, index: number) => V): Map<K, V> => {\n    return array.reduce((acc, element, index) => {\n      const key = toKey(element, index);\n      const value = toValue(element, index);\n      acc.set(key, value);\n      return acc;\n    }, new Map<K, V>());\n  },\n  toMultiMap: <T, K, V>(array: T[], toKey: (item: T) => K, toValue: (item: T) => V): Map<K, V[]> => {\n    const map = new Map<K, V[]>();\n    for (const item of array) {\n      const key = toKey(item);\n      const value = toValue(item);\n      const values = map.get(key);\n      if (values === undefined) {\n        map.set(key, [value]);\n      } else {\n        values.push(value);\n      }\n    }\n    return map;\n  },\n};\n","export class Capacity {\n  private _capacity = 0;\n\n  constructor(\n        private readonly min: number,\n        private readonly requiredMultiple: number,\n        private readonly capacityMultiple: number,\n  ) {\n    this._capacity = min;\n  }\n\n  get capacity(): number {\n    return this._capacity;\n  }\n  set capacity(capacity: number) {\n    this._capacity = capacity;\n  }\n\n  ensureCapacity(required: number): boolean {\n    const oldCapacity = this._capacity;\n    const hasIncreased = (required > this._capacity);\n    if (hasIncreased) {\n      this._capacity = Math.round(\n        Math.max(\n          this.min,\n          required * this.requiredMultiple,\n          oldCapacity * this.capacityMultiple,\n        )\n      );\n    }\n    return hasIncreased;\n  }\n}\n","import { Equality } from './compare';\n\nexport type WPKChangeDetector<T> = {\n    get: () => T;\n    compareAndUpdate: (next: T) => boolean;\n};\n\nexport const changeDetectorFactory = {\n  of: <T>(first: T, equals: Equality<T>): WPKChangeDetector<T> => {\n    let current: T = first;\n    return {\n      get() {\n        return current;\n      },\n      compareAndUpdate(next) {\n        const hasChanged = (current === undefined) || !equals(current, next);\n        current = next;\n        return hasChanged;\n      },\n    };\n  },\n  ofDoubleEquals: <T>(first: T): WPKChangeDetector<T> => {\n    return changeDetectorFactory.of<T>(first, (a, b) => a == b);\n  },\n  ofTripleEquals: <T>(first: T): WPKChangeDetector<T> => {\n    return changeDetectorFactory.of<T>(first, (a, b) => a === b);\n  },\n};\n","export type ColorRgbValues = readonly [number, number, number];\nexport type ColorRgbaValues = readonly [number, number, number, number];\n\nexport class Color {\n  static readonly BLACK = new Color(0, 0, 0);\n  static readonly RED = new Color(0, 0, 0);\n  static readonly GREEN = new Color(0, 0, 0);\n  static readonly BLUE = new Color(0, 0, 0);\n  static readonly YELLOW = new Color(1, 1, 0);\n  static readonly MAGENTA = new Color(1, 0, 1);\n  static readonly CYAN = new Color(0, 1, 1);\n  static readonly WHITE = new Color(1, 1, 1);\n\n  readonly valuesRgb: ColorRgbValues;\n  readonly valuesRgba: ColorRgbaValues;\n\n  constructor(\n    readonly r: number,\n    readonly g: number,\n    readonly b: number,\n    readonly a: number = 1,\n  ) {\n    this.valuesRgb = [r, g, b];\n    this.valuesRgba = [r, g, b, a];\n  }\n\n  equals(other: Color, epsilon = 1e-6): boolean {\n    return (\n      Math.abs(this.r - other.r) < epsilon\n      && Math.abs(this.g - other.g) < epsilon\n      && Math.abs(this.b - other.b) < epsilon\n      && Math.abs((this.a) - (other.a)) < epsilon\n    );\n  }\n};\n","export type PositiveInteger<T extends number> =\n  T extends 0\n  ? never\n  : `${T}` extends `${infer _}.${infer _}`\n  ? never\n  : `${T}` extends `-${infer _}`\n  ? never\n  : T\n  ;\n\nexport const mathFuncs = {\n  HALF_PI: 0.5 * Math.PI,\n  TWO_PI: 2 * Math.PI,\n\n  clamp: (value: number, min: number, max: number): number => {\n    return Math.max(min, Math.min(max, value));\n  },\n  gcd: (...numbers: number[]): number => {\n    if (numbers.length === 0) {\n      throw new Error('Array must contain at least one number.');\n    }\n    const gcdAB = (a: number, b: number): number => {\n      while (b !== 0) {\n        const temp = b;\n        b = a % b;\n        a = temp;\n      }\n      return Math.abs(a); // Ensure GCD is always positive\n    };\n    return numbers.reduce((acc, num) => gcdAB(acc, num));\n  },\n  geometricMean: (...elements: number[]): number => {\n    const product = elements.reduce((total, value) => total * value, 1);\n    return Math.pow(product, 1 / elements.length);\n  },\n  harmonicMean: (...elements: number[]): number => {\n    const sumReciprocals = elements.reduce((total, value) => total + (1 / value), 0);\n    return elements.length / sumReciprocals;\n  },\n  sumMapValues: <K, V extends number>(map: Map<K, V>): number => Array.from(map.values()).reduce((sum, value) => sum + value, 0),\n  nextMultipleOf: (num: number, multiple: number): number => Math.ceil(num / multiple) * multiple,\n};\n","import { Vector3 } from './Vector3';\n\nexport type QuaternionValues = readonly [number, number, number, number];\n\nexport class Quaternion {\n  static readonly IDENTITY = new Quaternion(0, 0, 0, 1);\n\n  readonly values: QuaternionValues;\n\n  constructor(\n    readonly x: number,\n    readonly y: number,\n    readonly z: number,\n    readonly w: number\n  ) {\n    this.values = [x, y, z, w];\n  }\n\n  static fromAxisAngle(axis: Vector3, radians: number): Quaternion {\n    const axisLength = axis.length();\n    if (axisLength < 1e-6) {\n      return Quaternion.IDENTITY;\n    }\n    const halfAngle = radians * 0.5;\n    const s = Math.sin(halfAngle);\n    const c = Math.cos(halfAngle);\n    const multiplier = s / axisLength;\n    return new Quaternion(\n      axis.x * multiplier,\n      axis.y * multiplier,\n      axis.z * multiplier,\n      c\n    );\n  }\n\n  conjugate(): Quaternion {\n    return new Quaternion(-this.x, -this.y, -this.z, this.w);\n  }\n\n  length(): number {\n    return Math.hypot(this.x, this.y, this.z, this.w);\n  }\n\n  lengthSquared(): number {\n    return this.x ** 2 + this.y ** 2 + this.z ** 2 + this.w ** 2;\n  }\n\n  multiply(multiplier: Quaternion): Quaternion {\n    const x1 = this.x;\n    const y1 = this.y;\n    const z1 = this.z;\n    const w1 = this.w;\n    const x2 = multiplier.x;\n    const y2 = multiplier.y;\n    const z2 = multiplier.z;\n    const w2 = multiplier.w;\n    return new Quaternion(\n      w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,\n      w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2,\n      w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2,\n      w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2\n    );\n  }\n\n  normalize(epsilon: number = 1e-6): Quaternion {\n    const lengthSq = this.lengthSquared();\n    if (lengthSq <= (epsilon * epsilon)) {\n      return Quaternion.IDENTITY;\n    }\n    const inverseLength = 1 / Math.sqrt(lengthSq);\n    return new Quaternion(\n      this.x * inverseLength,\n      this.y * inverseLength,\n      this.z * inverseLength,\n      this.w * inverseLength\n    );\n  }\n\n  slerp(target: Quaternion, proportion: number, epsilon = 1e-6): Quaternion {\n    if (proportion <= 0) {\n      return this;\n    }\n    if (proportion >= 1) {\n      return target;\n    }\n    let dot = this.x * target.x + this.y * target.y + this.z * target.z + this.w * target.w;\n    if (dot < 0) {\n      target = new Quaternion(-target.x, -target.y, -target.z, -target.w);\n      dot = -dot;\n    }\n    const theta_0 = Math.acos(dot);\n    const theta = theta_0 * proportion;\n    const sinTheta = Math.sin(theta_0);\n    if (sinTheta < epsilon) {\n      // fallback to linear interpolation to avoid division by zero\n      return new Quaternion(\n        this.x * (1 - proportion) + target.x * proportion,\n        this.y * (1 - proportion) + target.y * proportion,\n        this.z * (1 - proportion) + target.z * proportion,\n        this.w * (1 - proportion) + target.w * proportion\n      ).normalize();\n    }\n    const s0 = Math.cos(theta) - dot * Math.sin(theta) / sinTheta;\n    const s1 = Math.sin(theta) / sinTheta;\n    return new Quaternion(\n      s0 * this.x + s1 * target.x,\n      s0 * this.y + s1 * target.y,\n      s0 * this.z + s1 * target.z,\n      s0 * this.w + s1 * target.w\n    );\n  }\n}\n","export type Vector3Values = readonly [number, number, number];\n\nexport class Vector3 {\n  static readonly ZERO = new Vector3(0, 0, 0);\n  static readonly ONE = new Vector3(1, 1, 1);\n  static readonly X = new Vector3(1, 0, 0);\n  static readonly Y = new Vector3(0, 1, 0);\n  static readonly Z = new Vector3(0, 0, 1);\n\n  readonly values: Vector3Values;\n\n  constructor(\n    readonly x: number,\n    readonly y: number,\n    readonly z: number\n  ) {\n    this.values = [x, y, z];\n  }\n\n  cross(other: Vector3): Vector3 {\n    return new Vector3(\n      this.y * other.z - this.z * other.y,\n      this.z * other.x - this.x * other.z,\n      this.x * other.y - this.y * other.x,\n    );\n  }\n\n  dot(other: Vector3): number {\n    return this.x * other.x + this.y * other.y + this.z * other.z;\n  }\n\n  distanceTo(to: Vector3): number {\n    return this.minus(to).length();\n  }\n\n  distanceSquaredTo(to: Vector3): number {\n    return this.minus(to).lengthSquared();\n  }\n\n  equals(other: Vector3, epsilon = 1e-6): boolean {\n    return (\n      Math.abs(this.x - other.x) < epsilon\n      && Math.abs(this.y - other.y) < epsilon\n      && Math.abs(this.z - other.z) < epsilon\n    );\n  }\n\n  length(): number {\n    return Math.hypot(this.x, this.y, this.z);\n  }\n\n  lengthSquared(): number {\n    return this.x ** 2 + this.y ** 2 + this.z ** 2;\n  }\n\n  lerp(to: Vector3, proportion: number): Vector3 {\n    if (proportion <= 0) {\n      return this;\n    }\n    if (proportion >= 1) {\n      return to;\n    }\n    return new Vector3(\n      this.x + (to.x - this.x) * proportion,\n      this.y + (to.y - this.y) * proportion,\n      this.z + (to.z - this.z) * proportion,\n    );\n  }\n\n  midpoint(to: Vector3): Vector3 {\n    return this.plus(to).scale(0.5).normalize();\n  }\n\n  minus(other: Vector3): Vector3 {\n    return new Vector3(this.x - other.x, this.y - other.y, this.z - other.z);\n  }\n\n  negate(): Vector3 {\n    return new Vector3(-this.x, -this.y, -this.z);\n  }\n\n  normalize(): Vector3 {\n    const len = this.length();\n    return len === 0 ? Vector3.ZERO : this.scale(1 / len);\n  }\n\n  plus(other: Vector3): Vector3 {\n    return new Vector3(this.x + other.x, this.y + other.y, this.z + other.z);\n  }\n\n  scale(scalar: number): Vector3 {\n    return new Vector3(this.x * scalar, this.y * scalar, this.z * scalar);\n  }\n}\n","import { Quaternion } from './Quaternion';\nimport { Vector3 } from './Vector3';\n\nexport type CameraMatrixValues = [\n  number, number, number, number,\n  number, number, number, number,\n  number, number, number, number,\n  number, number, number, number,\n];\n\nexport class Camera {\n  private _position = Vector3.ZERO;\n  private _rotation = Quaternion.IDENTITY;\n  private _fieldOfViewDegrees = 60;\n  private _aspectRatio = 1;\n  private _near: number = 0.1;\n  private _far: number = 1000;\n  private isDirtyPosition: boolean = true;\n  private isDirtyRotation: boolean = true;\n  private isDirtyAspectRatio: boolean = true;\n  private isDirtyFieldOfView: boolean = true;\n  private isDirtyNearFar: boolean = true;\n  private isDirtyViewProjection: boolean = true;\n  private readonly _viewMatrix: CameraMatrixValues = [\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 1, 0,\n    0, 0, 0, 1,\n  ];\n  private readonly _projectionMatrix: CameraMatrixValues = [\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 1, -1,\n    0, 0, 2, 0,\n  ];\n  private readonly _viewProjectionMatrix: CameraMatrixValues = [\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 1, 0,\n    0, 0, 0, 1,\n  ];\n\n  get viewMatrix(): Readonly<CameraMatrixValues> {\n    this.flushChanges(true, false);\n    return this._viewMatrix;\n  }\n  get projectionMatrix(): Readonly<CameraMatrixValues> {\n    this.flushChanges(false, true);\n    return this._projectionMatrix;\n  }\n  get viewProjectionMatrix(): Readonly<CameraMatrixValues> {\n    this.flushChanges(true, true);\n    return this._viewProjectionMatrix;\n  }\n\n  get position(): Vector3 {\n    return this._position;\n  }\n  get rotation(): Quaternion {\n    return this._rotation;\n  }\n  get fieldOfViewDegrees(): number {\n    return this._fieldOfViewDegrees;\n  }\n  get aspectRatio(): number {\n    return this._aspectRatio;\n  }\n  get near(): number {\n    return this._near;\n  }\n  get far(): number {\n    return this._far;\n  }\n\n  setPosition(position: Vector3) {\n    this.isDirtyPosition = true;\n    this._position = position;\n  }\n  setRotation(rotation: Quaternion) {\n    this.isDirtyRotation = true;\n    this._rotation = rotation;\n  }\n  setFieldOfView(fieldOfView: number) {\n    if (fieldOfView <= 0 || fieldOfView >= 180) {\n      throw new Error(`FOV must be between 0 and 180 degrees but is ${fieldOfView}`);\n    }\n    this.isDirtyFieldOfView = true;\n    this._fieldOfViewDegrees = fieldOfView;\n  }\n  setAspectRatio(aspectRatio: number) {\n    this.isDirtyAspectRatio = true;\n    this._aspectRatio = aspectRatio;\n  }\n  setNearFar(near: number, far: number) {\n    if (near <= 0 || far <= 0) {\n      throw new Error(`Both near and far bounds must be positive but are [${near}, ${far}]`);\n    }\n    if (near >= far) {\n      throw new Error(`Near bound must be lower than far bound but are [${near}, ${far}]`);\n    }\n    this.isDirtyNearFar = true;\n    this._near = near;\n    this._far = far;\n  }\n\n  translate(offset: Vector3): void {\n    this.setPosition(this._position.plus(offset));\n  }\n\n  rotate(rotation: Quaternion): void {\n    this.setRotation(this._rotation.multiply(rotation).normalize());\n  }\n\n  private flushChanges(flushView: boolean, flushProjection: boolean): void {\n    if (flushView) {\n      this.updateView();\n    }\n    if (flushProjection) {\n      this.updateProjection();\n    }\n    if (flushView || flushProjection) {\n      this.updateViewProjection();\n    }\n  }\n\n  private updateView(): boolean {\n    if (!this.isDirtyPosition && !this.isDirtyRotation) {\n      return false;\n    }\n    const { x: rx, y: ry, z: rz, w: rw } = this._rotation;\n    const { x: px, y: py, z: pz } = this._position;\n\n    const x2 = rx + rx;\n    const y2 = ry + ry;\n    const z2 = rz + rz;\n\n    const xx = rx * x2;\n    const yy = ry * y2;\n    const zz = rz * z2;\n    const xy = rx * y2;\n    const xz = rx * z2;\n    const yz = ry * z2;\n    const wx = rw * x2;\n    const wy = rw * y2;\n    const wz = rw * z2;\n\n    const m00 = 1 - (yy + zz);\n    const m01 = xy + wz;\n    const m02 = xz - wy;\n    const m10 = xy - wz;\n    const m11 = 1 - (xx + zz);\n    const m12 = yz + wx;\n    const m20 = xz + wy;\n    const m21 = yz - wx;\n    const m22 = 1 - (xx + yy);\n\n    const vm = this._viewMatrix;\n    vm[0] = m00;\n    vm[1] = m01;\n    vm[2] = m02;\n    vm[4] = m10;\n    vm[5] = m11;\n    vm[6] = m12;\n    vm[8] = m20;\n    vm[9] = m21;\n    vm[10] = m22;\n    vm[12] = -(m00 * px + m01 * py + m02 * pz);\n    vm[13] = -(m10 * px + m11 * py + m12 * pz);\n    vm[14] = -(m20 * px + m21 * py + m22 * pz);\n\n    this.isDirtyPosition = false;\n    this.isDirtyRotation = false;\n    this.isDirtyViewProjection = true;\n    return true;\n  }\n\n  private updateProjection(): boolean {\n    if (!this.isDirtyFieldOfView && !this.isDirtyAspectRatio && !this.isDirtyNearFar) {\n      return false;\n    }\n    const fovRad = (this._fieldOfViewDegrees * Math.PI) / 180;\n    const f = 1.0 / Math.tan(fovRad / 2);\n    const near = this._near;\n    const far = this._far;\n    const nf = 1 / (near - far);\n\n    const pm = this._projectionMatrix;\n    pm[0] = f / this._aspectRatio;\n    pm[5] = f;\n    pm[10] = (far + near) * nf;\n    pm[14] = (2 * far * near) * nf;\n\n    this.isDirtyFieldOfView = false;\n    this.isDirtyAspectRatio = false;\n    this.isDirtyNearFar = false;\n    this.isDirtyViewProjection = true;\n    return true;\n  }\n\n  private updateViewProjection(): boolean {\n    if (!this.isDirtyViewProjection) {\n      return false;\n    }\n    const vm = this._viewMatrix;\n    const pm = this._projectionMatrix;\n    const vpm = this._viewProjectionMatrix;\n\n    const pm00 = pm[0];\n    const pm11 = pm[5];\n    const pm22 = pm[10];\n    const pm32 = pm[14];\n\n    vpm[0] = pm00 * vm[0];\n    vpm[1] = pm11 * vm[1];\n    vpm[2] = pm22 * vm[2] + pm32 * vm[3];\n    vpm[3] = -vm[2];\n\n    vpm[4] = pm00 * vm[4];\n    vpm[5] = pm11 * vm[5];\n    vpm[6] = pm22 * vm[6] + pm32 * vm[7];\n    vpm[7] = -vm[6];\n\n    vpm[8] = pm00 * vm[8];\n    vpm[9] = pm11 * vm[9];\n    vpm[10] = pm22 * vm[10] + pm32 * vm[11];\n    vpm[11] = -vm[10];\n\n    vpm[12] = pm00 * vm[12];\n    vpm[13] = pm11 * vm[13];\n    vpm[14] = pm22 * vm[14] + pm32 * vm[15];\n    vpm[15] = -vm[14];\n\n    this.isDirtyViewProjection = false;\n    return true;\n  }\n}\n","import { getLogger } from '../logging';\nimport { logFuncs } from '../utils';\nimport { Quaternion } from './Quaternion';\nimport { Vector3 } from './Vector3';\n\nexport type TransformationValues = [\n  number, number, number, number,\n  number, number, number, number,\n  number, number, number, number,\n  number, number, number, number,\n];\n\nconst LOGGER = getLogger('data');\n\nexport class Transformation {\n  private _position = Vector3.ZERO;\n  private _rotation = Quaternion.IDENTITY;\n  private _scale = Vector3.ONE;\n  private isDirtyPosition: boolean = true;\n  private isDirtyRotation: boolean = true;\n  private isDirtyScale: boolean = true;\n  private readonly _matrix: TransformationValues = [\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 1, 0,\n    0, 0, 0, 1,\n  ];\n\n  get matrix(): Readonly<TransformationValues> {\n    this.flushChanges();\n    return this._matrix;\n  }\n\n  get position(): Vector3 {\n    return this._position;\n  }\n  get rotation(): Quaternion {\n    return this._rotation;\n  }\n  get scale(): Vector3 {\n    return this._scale;\n  }\n\n  setPosition(position: Vector3) {\n    this.isDirtyPosition = true;\n    this._position = position;\n  }\n\n  setRotation(rotation: Quaternion) {\n    this.isDirtyRotation = true;\n    this._rotation = rotation;\n  }\n\n  setScale(scale: Vector3) {\n    if (scale.x <= 0 || scale.y <= 0 || scale.z <= 0) {\n      logFuncs.lazyWarn(LOGGER, () => `Cannot set scale component to non-positive value [${scale.x}, ${scale.y}, ${scale.z}]`);\n      return;\n    }\n    this.isDirtyScale = true;\n    this._scale = scale;\n  }\n\n  private flushChanges(): void {\n    if (this.isDirtyRotation || this.isDirtyScale) {\n      this._rotation = this._rotation.normalize();\n      const { x: sx, y: sy, z: sz } = this._scale;\n      const { x: rx, y: ry, z: rz, w: rw } = this._rotation;\n\n      const x2 = rx + rx;\n      const y2 = ry + ry;\n      const z2 = rz + rz;\n\n      const xx = rx * x2;\n      const yy = ry * y2;\n      const zz = rz * z2;\n      const xy = rx * y2;\n      const xz = rx * z2;\n      const yz = ry * z2;\n      const wx = rw * x2;\n      const wy = rw * y2;\n      const wz = rw * z2;\n\n      const m00 = (1 - (yy + zz)) * sx;\n      const m01 = (xy + wz) * sx;\n      const m02 = (xz - wy) * sx;\n      const m10 = (xy - wz) * sy;\n      const m11 = (1 - (xx + zz)) * sy;\n      const m12 = (yz + wx) * sy;\n      const m20 = (xz + wy) * sz;\n      const m21 = (yz - wx) * sz;\n      const m22 = (1 - (xx + yy)) * sz;\n\n      const m = this._matrix;\n      m[0] = m00;\n      m[1] = m01;\n      m[2] = m02;\n      m[4] = m10;\n      m[5] = m11;\n      m[6] = m12;\n      m[8] = m20;\n      m[9] = m21;\n      m[10] = m22;\n\n      this.isDirtyRotation = false;\n      this.isDirtyScale = false;\n    }\n\n    if (this.isDirtyPosition) {\n      const { x, y, z } = this._position;\n      const m = this._matrix;\n      m[12] = x;\n      m[13] = y;\n      m[14] = z;\n\n      this.isDirtyPosition = false;\n    }\n  }\n}\n","export type Vector2Values = readonly [number, number];\n\nexport class Vector2 {\n  static readonly ZERO = new Vector2(0, 0);\n  static readonly ONE = new Vector2(1, 1);\n  static readonly X = new Vector2(1, 0);\n  static readonly Y = new Vector2(0, 1);\n\n  readonly values: Vector2Values;\n\n  constructor(\n    readonly x: number,\n    readonly y: number,\n  ) {\n    this.values = [x, y];\n  }\n\n  dot(other: Vector2): number {\n    return this.x * other.x + this.y * other.y;\n  }\n\n  distanceTo(to: Vector2): number {\n    return this.minus(to).length();\n  }\n\n  distanceSquaredTo(to: Vector2): number {\n    return this.minus(to).lengthSquared();\n  }\n\n  equals(other: Vector2, epsilon = 1e-6): boolean {\n    return (\n      Math.abs(this.x - other.x) < epsilon\n      && Math.abs(this.y - other.y) < epsilon\n    );\n  }\n\n  length(): number {\n    return Math.hypot(this.x, this.y);\n  }\n\n  lengthSquared(): number {\n    return this.x ** 2 + this.y ** 2;\n  }\n\n  lerp(to: Vector2, proportion: number): Vector2 {\n    if (proportion <= 0) {\n      return this;\n    }\n    if (proportion >= 1) {\n      return to;\n    }\n    return new Vector2(\n      this.x + (to.x - this.x) * proportion,\n      this.y + (to.y - this.y) * proportion,\n    );\n  }\n\n  midpoint(to: Vector2): Vector2 {\n    return this.plus(to).scale(0.5).normalize();\n  }\n\n  minus(other: Vector2): Vector2 {\n    return new Vector2(this.x - other.x, this.y - other.y);\n  }\n\n  negate(): Vector2 {\n    return new Vector2(-this.x, -this.y);\n  }\n\n  normalize(): Vector2 {\n    const len = this.length();\n    return len === 0 ? Vector2.ZERO : this.scale(1 / len);\n  }\n\n  plus(other: Vector2): Vector2 {\n    return new Vector2(this.x + other.x, this.y + other.y);\n  }\n\n  scale(scalar: number): Vector2 {\n    return new Vector2(this.x * scalar, this.y * scalar);\n  }\n}\n","import { getLogger } from './logging';\nimport { Vector3 } from './math';\nimport { WPKIndices, WPKMesh, WPKMeshParametersDeclaration, WPKMeshTemplateCreator, WPKVertices } from './types';\nimport { logFuncs, mathFuncs } from './utils';\n\nconst LOGGER = getLogger('mesh');\n\nexport const meshFuncs = {\n  UINT32_INDEX_COUNT: 1 << 16,\n  VERTICES_PER_TRIANGLE: 3,\n\n  cullMode: (mesh: WPKMesh): GPUCullMode => (mesh.winding === 'cw')\n    ? 'front'\n    : 'back',\n  indicesType: (mesh: WPKMesh): GPUIndexFormat => (mesh.indices.length < meshFuncs.UINT32_INDEX_COUNT)\n    ? 'uint16'\n    : 'uint32',\n  indicesCount: (mesh: WPKMesh): number => mesh.indices.length * 3,\n  indicesBytesLength: (mesh: WPKMesh): number => {\n    const indicesCount = meshFuncs.indicesCount(mesh);\n    return (indicesCount < meshFuncs.UINT32_INDEX_COUNT)\n      ? indicesCount * 2\n      : indicesCount * 4;\n  },\n  toIndicesData: (mesh: WPKMesh): ArrayBuffer => {\n    const indicesType = meshFuncs.indicesType(mesh);\n    const flatIndices = mesh.indices.flatMap(indices => indices.values);\n    const TypedArrayConstructor = (indicesType === 'uint16')\n      ? Uint16Array\n      : Uint32Array;\n    const typedArray = new TypedArrayConstructor(flatIndices);\n    const byteLength = typedArray.byteLength;\n    if (byteLength % 4 === 0) {\n      return typedArray.buffer;\n    }\n    const paddedByteLength = mathFuncs.nextMultipleOf(byteLength, 4);\n    const buffer = new ArrayBuffer(paddedByteLength);\n    const targetView = new TypedArrayConstructor(buffer);\n    targetView.set(typedArray);\n    return buffer;\n  },\n  toVerticesData: (mesh: WPKMesh): ArrayBuffer => {\n    const flatVertices = mesh.vertices.flatMap(indices => indices.values);\n    const verticesArray = new Float32Array(flatVertices);\n    return verticesArray.buffer;\n  },\n};\n\nexport const meshTemplateFactory = {\n  of: <TParameters extends WPKMeshParametersDeclaration>(parameters: TParameters, toMesh: WPKMeshTemplateCreator<TParameters>) => ({\n    parameters,\n    toMesh,\n  }),\n};\n\nexport const meshFactory = {\n  of: (type: GPUPrimitiveTopology, vertices: WPKVertices, indices: WPKIndices, winding: GPUFrontFace): WPKMesh => {\n    return {\n      topology: type,\n      vertices,\n      indices,\n      winding,\n    };\n  },\n  triangle: (topProportion: number, axis: Vector3 = Vector3.Z): WPKMesh => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating triangle mesh with top proportion ${topProportion}`);\n    const axisNormalized = axis.normalize();\n\n    // Pick a non-parallel reference vector for tangent\n    const up: Vector3 = Math.abs(axisNormalized.y) < 0.99 ? Vector3.Y : Vector3.X;\n    const tangent = up.cross(axisNormalized).normalize();\n    const bitangent = axisNormalized.cross(tangent); // already normalized due to orthogonality\n\n    // Define triangle in 2D: base at y = -1, top at y = 1\n    const baseY = -1;\n    const topY = 1;\n    const leftX = -1;\n    const rightX = 1;\n    const topX = leftX + (rightX - leftX) * topProportion;\n\n    const localPoints: [number, number][] = [\n      [leftX, baseY],\n      [rightX, baseY],\n      [topX, topY],\n    ];\n\n    // Project into 3D using tangent/bitangent vectors\n    const vertices: WPKVertices = [];\n    for (const [x, y] of localPoints) {\n      const vx = tangent.x * x + bitangent.x * y;\n      const vy = tangent.y * x + bitangent.y * y;\n      const vz = tangent.z * x + bitangent.z * y;\n      vertices.push(new Vector3(vx, vy, vz));\n    }\n\n    const indices: WPKIndices = [new Vector3(0, 1, 2)];\n    return {\n      topology: 'triangle-list',\n      vertices,\n      indices,\n      winding: 'cw',\n    };\n  },\n  cube: (): WPKMesh => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating cube mesh');\n    const vertices: Vector3[] = [\n      // Front face\n      new Vector3(-1, -1, 1), // front bottom left\n      new Vector3(1, -1, 1), // front bottom right\n      new Vector3(1, 1, 1), // front top right\n      new Vector3(-1, 1, 1), // front top left\n      // Back face\n      new Vector3(-1, -1, -1), // back bottom left\n      new Vector3(-1, 1, -1), // back top left\n      new Vector3(1, 1, -1), // back top right\n      new Vector3(1, -1, -1), // back bottom right\n    ];\n    const indices: Vector3[] = [\n      // Front\n      new Vector3(0, 1, 2),\n      new Vector3(0, 2, 3),\n      // Top\n      new Vector3(3, 2, 6),\n      new Vector3(3, 6, 5),\n      // Back\n      new Vector3(5, 6, 7),\n      new Vector3(5, 7, 4),\n      // Bottom\n      new Vector3(4, 7, 1),\n      new Vector3(4, 1, 0),\n      // Left\n      new Vector3(4, 0, 3),\n      new Vector3(4, 3, 5),\n      // Right\n      new Vector3(1, 7, 6),\n      new Vector3(1, 6, 2),\n    ];\n    return {\n      topology: 'triangle-list',\n      vertices,\n      indices,\n      winding: 'cw',\n    };\n  },\n  sphere(subdivisions: number): WPKMesh {\n    logFuncs.lazyDebug(LOGGER, () => `Creating sphere mesh with sub divisions ${subdivisions}`);\n    const phi = (1 + Math.sqrt(5)) / 2;\n    const unnormalizedVertices: Vector3[] = [\n      new Vector3(-1, phi, 0),\n      new Vector3(1, phi, 0),\n      new Vector3(-1, -phi, 0),\n      new Vector3(1, -phi, 0),\n      new Vector3(0, -1, phi),\n      new Vector3(0, 1, phi),\n      new Vector3(0, -1, -phi),\n      new Vector3(0, 1, -phi),\n      new Vector3(phi, 0, -1),\n      new Vector3(phi, 0, 1),\n      new Vector3(-phi, 0, -1),\n      new Vector3(-phi, 0, 1),\n    ];\n    const vertices = unnormalizedVertices.map(vec => vec.normalize());\n    const baseIndices: Vector3[] = [\n      new Vector3(0, 11, 5),\n      new Vector3(0, 5, 1),\n      new Vector3(0, 1, 7),\n      new Vector3(0, 7, 10),\n      new Vector3(0, 10, 11),\n      new Vector3(1, 5, 9),\n      new Vector3(5, 11, 4),\n      new Vector3(11, 10, 2),\n      new Vector3(10, 7, 6),\n      new Vector3(7, 1, 8),\n      new Vector3(3, 9, 4),\n      new Vector3(3, 4, 2),\n      new Vector3(3, 2, 6),\n      new Vector3(3, 6, 8),\n      new Vector3(3, 8, 9),\n      new Vector3(4, 9, 5),\n      new Vector3(2, 4, 11),\n      new Vector3(6, 2, 10),\n      new Vector3(8, 6, 7),\n      new Vector3(9, 8, 1),\n    ];\n    const indices: Vector3[] = [];\n    const cache = new Map<string, number>();\n\n    const getOrCreateMidpoint = (a: number, b: number): number => {\n      const key = [Math.min(a, b), Math.max(a, b)].join('|');\n      if (cache.has(key)) {\n        return cache.get(key) as number;\n      }\n      const midpoint = vertices[a].midpoint(vertices[b]);\n      const index = vertices.length;\n      vertices.push(midpoint);\n      cache.set(key, index);\n      return index;\n    };\n\n    const subdivide = (a: number, b: number, c: number, depth: number) => {\n      if (depth === 0) {\n        indices.push(new Vector3(a, b, c));\n      } else {\n        const ab = getOrCreateMidpoint(a, b);\n        const bc = getOrCreateMidpoint(b, c);\n        const ca = getOrCreateMidpoint(c, a);\n        subdivide(a, ab, ca, depth - 1);\n        subdivide(b, bc, ab, depth - 1);\n        subdivide(c, ca, bc, depth - 1);\n        subdivide(ab, bc, ca, depth - 1);\n      }\n    };\n\n    for (const vec of baseIndices) {\n      subdivide(vec.x, vec.y, vec.z, subdivisions);\n    }\n\n    return {\n      topology: 'triangle-list',\n      vertices,\n      indices,\n      winding: 'cw',\n    };\n  }\n};\n","import { WPKResource } from './types';\nimport { arrayFuncs } from './utils';\n\nexport const resourceFactory = {\n  ofCached: <T>(resource: WPKResource<T>): WPKResource<T> => {\n    let object: T | undefined;\n    return {\n      update(device, queue, encoder) {\n        if (object === undefined) {\n          resource.update(device, queue, encoder);\n          object = resource.get();\n        }\n      },\n      get() {\n        return resource.get();\n      },\n      clean() {\n        object = undefined;\n        resource.clean();\n      },\n    };\n  },\n  ofFunc: <T>(func: () => T, isDirty: () => boolean = () => true): WPKResource<T> => {\n    let object: T | undefined;\n    return {\n      update(_device, _queue, _encoder) {\n        if (object === undefined || isDirty()) {\n          object = func();\n        }\n      },\n      get() {\n        return resourceFactory.getOrThrow(object, 'resource func');\n      },\n      clean() {\n        object = undefined;\n      },\n    };\n  },\n  ofArray: <T>(resources: WPKResource<T>[]): WPKResource<T[]> => {\n    return {\n      update(device, queue, encoder) {\n        resources.forEach((resource) => resource.update(device, queue, encoder));\n      },\n      get() {\n        return resources.map(resource => resource.get());\n      },\n      clean() {\n        resources.forEach(resource => resource.clean());\n      },\n    };\n  },\n  ofCachedFromDependencies: <DependencyResources extends readonly WPKResource<any>[], T>(\n    dependencyResources: DependencyResources,\n    createWithValues: (\n      device: GPUDevice,\n      queue: GPUQueue,\n      encoder: GPUCommandEncoder,\n      values: { [K in keyof DependencyResources]: DependencyResources[K] extends WPKResource<infer R> ? R : never },\n    ) => T\n  ): WPKResource<T> => {\n    let cachedValue: T | undefined;\n    let lastDependencies: any[] = [];\n    return {\n      update(device, queue, encoder) {\n        dependencyResources.forEach((dependencyResource) => dependencyResource.update(device, queue, encoder));\n        const currentDependencies = dependencyResources.map((dependencyResource) => dependencyResource.get());\n        if (!arrayFuncs.equals(lastDependencies, currentDependencies) || cachedValue === undefined) {\n          cachedValue = createWithValues(device, queue, encoder, currentDependencies as any);\n          lastDependencies = currentDependencies;\n        }\n      },\n      get() {\n        return resourceFactory.getOrThrow(cachedValue, 'cached resource value');\n      },\n      clean() {\n        dependencyResources.forEach(resource => resource.clean());\n      },\n    };\n  },\n  getOrThrow: <T>(t: T | undefined, name: string): T => {\n    if (t === undefined) {\n      throw Error(`Cannot get ${name} before update() is called`);\n    }\n    return t;\n  },\n};\n","import { getLogger } from './logging';\nimport { resourceFactory } from './resources';\nimport { WPKBufferMutable, WPKBufferResizeable, WPKMutatedData, WPKResource, WPKTrackedBuffer } from './types';\nimport { Capacity, CopySlice, logFuncs, mathFuncs, ValueSlices } from './utils';\n\nconst MINIMUM_BYTES_LENGTH = 32;\nconst VALID_BYTES_MULTIPLE = 16;\n\nconst LOGGER = getLogger('buffer');\n\nconst createLabeller = (label: string) => {\n  let index = 0;\n  let currentLabel = `${label}-${index}`;\n  return {\n    current: (): string => currentLabel,\n    next: (): string => {\n      index++;\n      currentLabel = `${label}-${index}`;\n      return currentLabel;\n    },\n  };\n};\n\nconst checkNotDestroyed = (state: WPKManagedBufferState): void => {\n  if (state === WPKManagedBufferState.Destroyed) {\n    throw Error('Cannot use managed buffer after being destroyed');\n  }\n};\nconst toValidSize = (label: string, bytesLength: number): number => {\n  const clampedBytesLength = Math.max(MINIMUM_BYTES_LENGTH, bytesLength);\n  const validSize = mathFuncs.nextMultipleOf(clampedBytesLength, VALID_BYTES_MULTIPLE);\n  if (validSize > bytesLength) {\n    logFuncs.lazyDebug(LOGGER, () => `Increasing desired length of buffer '${label}' from ${bytesLength} to valid length ${validSize}`);\n  }\n  return validSize;\n};\n\nenum WPKManagedBufferState {\n  Initialized,\n  New,\n  Reused,\n  Destroyed,\n}\n\nexport const bufferFactory = {\n  ofData: (data: ArrayBuffer, label: string, usage: GPUBufferUsageFlags, requiresReadBack: boolean): WPKResource<WPKTrackedBuffer> => {\n    const labeller = createLabeller(label);\n    logFuncs.lazyDebug(LOGGER, () => `Creating buffer '${labeller.current()}' of usage ${usageToString(usage)} from data of byte length ${data.byteLength}`);\n    const size = toValidSize(labeller.current(), data.byteLength);\n    if (size > data.byteLength) {\n      logFuncs.lazyTrace(LOGGER, () => `Aligning buffer ${labeller.current()} to new size ${size}`);\n      const alignedBuffer = new ArrayBuffer(size);\n      new Uint8Array(alignedBuffer).set(new Uint8Array(data));\n      data = alignedBuffer;\n    }\n    usage |= GPUBufferUsage.COPY_DST;\n    if (requiresReadBack) {\n      usage |= GPUBufferUsage.COPY_SRC;\n    }\n    let state = WPKManagedBufferState.Initialized;\n    let trackedBuffer: WPKTrackedBuffer | undefined;\n    return {\n      update(device, queue, _encoder) {\n        checkNotDestroyed(state);\n        if (trackedBuffer === undefined) {\n          labeller.next();\n          logFuncs.lazyTrace(LOGGER, () => `Creating new buffer ${labeller.current()} of size ${size} and usage ${usageToString(usage)}`);\n          const buffer = device.createBuffer({\n            label: labeller.current(),\n            size,\n            usage,\n          });\n          logFuncs.lazyTrace(LOGGER, () => `Writing data to new buffer ${labeller.current()} with queue`);\n          queue.writeBuffer(buffer, 0, data);\n          state = WPKManagedBufferState.New;\n          const destroy = () => {\n            state = WPKManagedBufferState.Destroyed;\n            buffer.destroy();\n          };\n          trackedBuffer = {\n            isNew: true,\n            bytesLength: size,\n            buffer,\n            destroy,\n          };\n        } else {\n          logFuncs.lazyTrace(LOGGER, () => `Reusing buffer ${labeller.current()}`);\n          if (state === WPKManagedBufferState.New) {\n            state = WPKManagedBufferState.Reused;\n            trackedBuffer = {\n              ...trackedBuffer,\n              isNew: false,\n            };\n          }\n        }\n      },\n      get() {\n        return resourceFactory.getOrThrow(trackedBuffer, `tracked buffer ${label}`);\n      },\n      clean() {\n      },\n    };\n  },\n  ofSize: (bytesLength: number, label: string, usage: GPUBufferUsageFlags, requiresReadBack: boolean): WPKResource<WPKTrackedBuffer> => {\n    const labeller = createLabeller(label);\n    logFuncs.lazyDebug(LOGGER, () => `Creating buffer '${labeller.current()}' of usage ${usageToString(usage)} of byte length ${bytesLength}`);\n    if (requiresReadBack) {\n      usage |= GPUBufferUsage.COPY_SRC;\n    }\n    const size = toValidSize(labeller.current(), bytesLength);\n    let state = WPKManagedBufferState.Initialized;\n    let trackedBuffer: WPKTrackedBuffer | undefined;\n    return {\n      update(device, _queue, _encoder) {\n        checkNotDestroyed(state);\n        if (trackedBuffer === undefined) {\n          labeller.next();\n          logFuncs.lazyTrace(LOGGER, () => `Creating new buffer ${labeller.current()} of size ${size} and usage ${usageToString(usage)}`);\n          const buffer = device.createBuffer({\n            label: labeller.current(),\n            size,\n            usage,\n          });\n          state = WPKManagedBufferState.New;\n          trackedBuffer = {\n            buffer,\n            bytesLength: size,\n            isNew: true,\n            destroy() {\n              state = WPKManagedBufferState.Destroyed;\n              buffer.destroy();\n            },\n          };\n        } else {\n          logFuncs.lazyTrace(LOGGER, () => `Reusing buffer ${labeller.current()}`);\n          if (state === WPKManagedBufferState.New) {\n            state = WPKManagedBufferState.Reused;\n            trackedBuffer = {\n              ...trackedBuffer,\n              isNew: false,\n            };\n          }\n        }\n      },\n      get() {\n        return resourceFactory.getOrThrow(trackedBuffer, `tracked buffer ${label}`);\n      },\n      clean() {\n      },\n    };\n  },\n  ofResizeable: (copyDataOnResize: boolean, label: string, usage: GPUBufferUsageFlags, requiresReadBack: boolean): WPKBufferResizeable & WPKResource<WPKTrackedBuffer> => {\n    const labeller = createLabeller(label);\n    logFuncs.lazyDebug(LOGGER, () => `Creating resizeable buffer '${labeller.current()}' of usage ${usageToString(usage)}`);\n    const oldBuffers: GPUBuffer[] = [];\n    let currentBuffer: GPUBuffer | undefined;\n    const capacity = new Capacity(MINIMUM_BYTES_LENGTH, 1.2, 1.5);\n    let previousBytesLength = capacity.capacity;\n    let desiredBytesLength = 0;\n    let state = WPKManagedBufferState.Initialized;\n    let trackedBuffer: WPKTrackedBuffer | undefined;\n    if (copyDataOnResize) {\n      usage |= GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST;\n    }\n    if (requiresReadBack) {\n      usage |= GPUBufferUsage.COPY_SRC;\n    }\n    return {\n      resize(bytesLength) {\n        logFuncs.lazyDebug(LOGGER, () => `Resizing buffer ${label} to desired size ${bytesLength}`);\n        desiredBytesLength = bytesLength;\n      },\n      update(device, queue, encoder) {\n        checkNotDestroyed(state);\n        if (trackedBuffer === undefined || desiredBytesLength > capacity.capacity) {\n          previousBytesLength = capacity.capacity;\n          capacity.ensureCapacity(desiredBytesLength);\n          capacity.capacity = toValidSize(labeller.current(), capacity.capacity);\n          labeller.next();\n          logFuncs.lazyTrace(LOGGER, () => `Creating new buffer ${labeller.current()} of size ${capacity.capacity} and usage ${usageToString(usage)}`);\n          const previousBuffer = currentBuffer;\n          const newBuffer = currentBuffer = device.createBuffer({\n            label: labeller.current(),\n            size: capacity.capacity,\n            usage,\n          });\n          state = WPKManagedBufferState.New;\n          trackedBuffer = {\n            bytesLength: capacity.capacity,\n            buffer: currentBuffer,\n            isNew: true,\n            destroy() {\n              state = WPKManagedBufferState.Destroyed;\n              newBuffer.destroy();\n            },\n          };\n          if (previousBuffer !== undefined) {\n            if (copyDataOnResize) {\n              const copySize = Math.min(previousBytesLength, capacity.capacity); // in case reducing capacity is supported\n              if (copySize > 0) {\n                logFuncs.lazyTrace(LOGGER, () => `Copy ${copySize} bytes of data to buffer ${labeller.current()} from previous`);\n                encoder.copyBufferToBuffer(previousBuffer, currentBuffer, copySize);\n              }\n            }\n            oldBuffers.push(previousBuffer);\n          }\n        } else if (trackedBuffer !== undefined && state === WPKManagedBufferState.New) {\n          logFuncs.lazyTrace(LOGGER, () => `Reusing buffer ${labeller.current()}`);\n          state = WPKManagedBufferState.Reused;\n          trackedBuffer = {\n            ...trackedBuffer,\n            isNew: false,\n          };\n        }\n      },\n      get() {\n        return resourceFactory.getOrThrow(trackedBuffer, `tracked buffer ${label}`);\n      },\n      clean() {\n        oldBuffers.forEach((buffer) => {\n          logFuncs.lazyDebug(LOGGER, () => `Destroying old buffer ${buffer.label}`);\n          buffer.destroy();\n        });\n        oldBuffers.length = 0;\n      },\n    };\n  },\n  ofMutable: (bytesLength: number, label: string, usage: GPUBufferUsageFlags, requiresReadBack: boolean): WPKBufferMutable<number> & WPKResource<WPKTrackedBuffer> => {\n    const labeller = createLabeller(label);\n    logFuncs.lazyDebug(LOGGER, () => `Creating mutable buffer '${labeller.current()}' of usage ${usageToString(usage)} from data of byte length ${bytesLength}`);\n    const size = toValidSize(labeller.current(), bytesLength);\n    usage |= GPUBufferUsage.COPY_DST;\n    if (requiresReadBack) {\n      usage |= GPUBufferUsage.COPY_SRC;\n    }\n    let state = WPKManagedBufferState.Initialized;\n    let trackedBuffer: WPKTrackedBuffer | undefined;\n    const mutatedDataArray: WPKMutatedData[] = [];\n    return {\n      mutate(data, index) {\n        logFuncs.lazyInfo(LOGGER, () => `Mutating data for mutable buffer ${labeller.current()}`);\n        mutatedDataArray.push({ data, index });\n      },\n      update(device, queue, _encoder) {\n        checkNotDestroyed(state);\n        if (trackedBuffer === undefined) {\n          labeller.next();\n          logFuncs.lazyTrace(LOGGER, () => `Creating new buffer ${labeller.current()} of size ${size} and usage ${usageToString(usage)}`);\n          const buffer = device.createBuffer({\n            label: labeller.current(),\n            size,\n            usage,\n          });\n          state = WPKManagedBufferState.New;\n          trackedBuffer = {\n            bytesLength: size,\n            buffer,\n            isNew: true,\n            destroy() {\n              state = WPKManagedBufferState.Destroyed;\n              buffer.destroy();\n            },\n          };\n        } else {\n          logFuncs.lazyTrace(LOGGER, () => `Reusing buffer ${labeller.current()}`);\n          if (state === WPKManagedBufferState.New) {\n            state = WPKManagedBufferState.Reused;\n            trackedBuffer = {\n              ...trackedBuffer,\n              isNew: false,\n            };\n          }\n        }\n        const { buffer } = trackedBuffer;\n        for (const { data, index } of mutatedDataArray) {\n          logFuncs.lazyTrace(LOGGER, () => `Writing mutated data to buffer ${labeller.current()} at index ${index} and length ${data.byteLength} using queue`);\n          queue.writeBuffer(buffer, index, data);\n        }\n        mutatedDataArray.length = 0;\n      },\n      get() {\n        return resourceFactory.getOrThrow(trackedBuffer, `tracked buffer ${label}`);\n      },\n      clean() {\n      },\n    };\n  },\n  ofStaged: (label: string, usage: GPUBufferUsageFlags, requiresReadBack: boolean): WPKBufferMutable<CopySlice[]> & WPKResource<WPKTrackedBuffer> => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating staged buffer '${label}' of usage ${usageToString(usage)}`);\n    const stagingLabel = `${label}-staging`;\n    const backingLabel = `${label}-backing`;\n    const staging = bufferFactory.ofResizeable(false, stagingLabel, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, requiresReadBack);\n    const backing = bufferFactory.ofResizeable(true, backingLabel, usage | GPUBufferUsage.COPY_DST, requiresReadBack);\n    let mutatedSlices: ValueSlices<ArrayBuffer> | undefined = undefined;\n    return {\n      mutate(data, target) {\n        logFuncs.lazyDebug(LOGGER, () => `Mutating data for staged buffer ${label}, values bytes: ${data.byteLength}, target: ${JSON.stringify(target)}`);\n        mutatedSlices = {\n          values: data,\n          copySlices: target,\n        };\n      },\n      update(device, queue, encoder) {\n        if (mutatedSlices !== undefined) {\n          logFuncs.lazyTrace(LOGGER, () => `Staging data to buffer ${stagingLabel}`);\n          const { values, copySlices } = mutatedSlices;\n          const backingSizeRequired = copySlices.reduce((max, copySlice) => Math.max(max, copySlice.toIndex + copySlice.length), 0);\n          logFuncs.lazyTrace(LOGGER, () => `Resizing buffer ${stagingLabel} to ${values.byteLength}`);\n          logFuncs.lazyTrace(LOGGER, () => `Resizing buffer ${backingLabel} to ${backingSizeRequired}`);\n          staging.resize(values.byteLength);\n          backing.resize(backingSizeRequired);\n          backing.update(device, queue, encoder);\n          staging.update(device, queue, encoder);\n          const backingBuffer = backing.get().buffer;\n          const stagingBuffer = staging.get().buffer;\n          logFuncs.lazyTrace(LOGGER, () => `Writing staging data of length ${values.byteLength} to buffer ${stagingLabel} using queue`);\n          queue.writeBuffer(stagingBuffer, 0, values);\n          for (const copySlice of copySlices) {\n            const { length, min, toIndex } = copySlice;\n            logFuncs.lazyTrace(LOGGER, () => `Copy staging data from ${stagingLabel} at index ${min} to ${backingLabel} at index ${toIndex} of length ${length} using encoder`);\n            encoder.copyBufferToBuffer(stagingBuffer, min, backingBuffer, toIndex, length);\n          }\n          mutatedSlices = undefined;\n        }\n      },\n      get() {\n        return backing.get();\n      },\n      clean() {\n        staging.clean();\n        backing.clean();\n      },\n    };\n  },\n};\n\nexport const usageToString = (usage: GPUBufferUsageFlags): string => {\n  const flagNames: string[] = [];\n  if ((usage & GPUBufferUsage.COPY_DST) === GPUBufferUsage.COPY_DST) { flagNames.push('COPY_DST'); }\n  if ((usage & GPUBufferUsage.COPY_SRC) === GPUBufferUsage.COPY_SRC) { flagNames.push('COPY_SRC'); }\n  if ((usage & GPUBufferUsage.INDEX) === GPUBufferUsage.INDEX) { flagNames.push('INDEX'); }\n  if ((usage & GPUBufferUsage.INDIRECT) === GPUBufferUsage.INDIRECT) { flagNames.push('INDIRECT'); }\n  if ((usage & GPUBufferUsage.MAP_READ) === GPUBufferUsage.MAP_READ) { flagNames.push('MAP_READ'); }\n  if ((usage & GPUBufferUsage.MAP_WRITE) === GPUBufferUsage.MAP_WRITE) { flagNames.push('MAP_WRITE'); }\n  if ((usage & GPUBufferUsage.QUERY_RESOLVE) === GPUBufferUsage.QUERY_RESOLVE) { flagNames.push('QUERY_RESOLVE'); }\n  if ((usage & GPUBufferUsage.STORAGE) === GPUBufferUsage.STORAGE) { flagNames.push('STORAGE'); }\n  if ((usage & GPUBufferUsage.UNIFORM) === GPUBufferUsage.UNIFORM) { flagNames.push('UNIFORM'); }\n  if ((usage & GPUBufferUsage.VERTEX) === GPUBufferUsage.VERTEX) { flagNames.push('VERTEX'); }\n  return `[${flagNames.join(', ')}]`;\n};\n","import { getLogger } from './logging';\nimport { WPKBufferLayoutEntry, WPKDatumBridgeMarshalled, WPKMarshaller } from './types';\nimport { logFuncs } from './utils';\n\nconst LOGGER = getLogger('data');\n\nexport const marshallerFactory = {\n  ofLayoutEntries: <T>(\n    layoutEntries: Record<string, WPKBufferLayoutEntry<WPKDatumBridgeMarshalled<T>>>,\n    totalStride: number,\n  ): WPKMarshaller<T> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Create marshaller');\n    const datumBridges = Object.values(layoutEntries).map(entry => entry.bridge);\n    logFuncs.lazyTrace(LOGGER, () => `Creating marshaller with total stride ${totalStride}`);\n    return {\n      encode(instances) {\n        logFuncs.lazyTrace(LOGGER, () => `Encoding ${instances.length} instances of total stride ${totalStride} with format ${JSON.stringify(layoutEntries)}`);\n        const totalSize = instances.length * totalStride;\n        logFuncs.lazyTrace(LOGGER, () => `Creating data view to hold extracted instance data of size ${totalSize}`);\n        const buffer = new ArrayBuffer(totalSize);\n        const dataView = new DataView(buffer);\n        instances.forEach((instance, index) => {\n          logFuncs.lazyTrace(LOGGER, () => `Extracting data from instance ${index + 1}/${instances.length} ${JSON.stringify(instance)}`);\n          datumBridges.forEach((datumBridge) => datumBridge.instanceToDataView(index * totalStride, instance, dataView));\n        });\n        return buffer;\n      },\n    };\n  },\n};\n","import { bufferFactory } from './buffer-factory';\nimport { getLogger } from './logging';\nimport { marshallerFactory } from './marshall';\nimport { meshFuncs } from './mesh-factories';\nimport { resourceFactory } from './resources';\nimport { WPKBufferFormatMap, WPKBufferLayoutEditable, WPKBufferLayouts, WPKBufferResources, WPKDispatchParamsDetail, WPKEntityCache, WPKMesh, WPKMeshBufferResource, WPKMutator, WPKResource, WPKTrackedBuffer, WPKUniformCache, WPKBufferLayoutUniform, WPKBufferLayoutMarshalled } from './types';\nimport { CopySlice, logFuncs, ValueSlices } from './utils';\n\nconst LOGGER = getLogger('buffer');\n\nexport const bufferResourcesFactory = {\n  ofDispatch: <TEntryPoints extends string[]>(\n    name: string,\n    bufferLayout: WPKBufferLayoutUniform<WPKDispatchParamsDetail<TEntryPoints>>,\n    params: WPKResource<WPKDispatchParamsDetail<TEntryPoints>>,\n    requiresReadBack: boolean\n  ): WPKResource<WPKTrackedBuffer> => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating dispatch buffer ${name}`);\n    const label = toBufferLabel(name, 'dispatch');\n    const { entries, stride, usage } = bufferLayout;\n    const marshaller = marshallerFactory.ofLayoutEntries(entries, stride);\n    const dispatchBuffer = bufferFactory.ofMutable(stride, label, usage, requiresReadBack);\n    return resourceFactory.ofCachedFromDependencies(\n      [params] as const,\n      (device, queue, encoder, values) => {\n        const marshalledData = marshaller.encode([values[0]]);\n        dispatchBuffer.mutate(marshalledData, 0);\n        dispatchBuffer.update(device, queue, encoder);\n        return dispatchBuffer.get();\n      }\n    );\n  },\n  ofMesh: (name: string, mesh: WPKMesh, requiresReadBack: boolean): WPKMeshBufferResource => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating mesh buffer ${name}`);\n    const indices = bufferFactory.ofData(meshFuncs.toIndicesData(mesh), `${name}-indices`, GPUBufferUsage.INDEX, requiresReadBack);\n    const vertices = bufferFactory.ofData(meshFuncs.toVerticesData(mesh), `${name}-vertices`, GPUBufferUsage.VERTEX, requiresReadBack);\n    return {\n      indices,\n      vertices,\n    };\n  },\n  ofBufferLayouts: <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>(\n    name: string,\n    uniformCache: WPKUniformCache<TUniform, boolean>,\n    entityCache: WPKEntityCache<TEntity, boolean, boolean>,\n    bufferLayouts: WPKBufferLayouts<TUniform, TEntity>,\n    requiresReadBack: boolean\n  ): WPKBufferResources<TUniform, TEntity, TBufferFormatMap> => {\n    const initialEntities = entityCache.calculateChanges().values;\n    const uniformMutators: WPKMutator<TUniform>[] = [];\n    const entityMutators: WPKMutator<ValueSlices<TEntity[]>>[] = [];\n    const buffers: Record<string, WPKResource<WPKTrackedBuffer>> = {};\n    logFuncs.lazyDebug(LOGGER, () => `Create buffer resources for ${name}`);\n    logFuncs.lazyDebug(LOGGER, () => `Create uniform buffer resources for ${name}`);\n    for (const [bufferName, bufferLayout] of Object.entries(bufferLayouts)) {\n      const { structType } = bufferLayout;\n      if (structType === 'uniform') {\n        const uniformBufferResource = bufferResourcesFactory.ofUniform(name, bufferName, bufferLayout, uniformCache, requiresReadBack);\n        if (Array.isArray(uniformBufferResource)) {\n          const [buffer, mutator] = uniformBufferResource;\n          buffers[bufferName] = buffer;\n          uniformMutators.push(mutator);\n        } else {\n          buffers[bufferName] = uniformBufferResource;\n        }\n      } else {\n        if (structType !== 'varyings') {\n          const bufferResource = (structType === 'editable')\n            ? bufferResourcesFactory.ofEditable(name, bufferName, bufferLayout, entityCache, requiresReadBack)\n            : (structType === 'marshalled')\n              ? bufferResourcesFactory.ofMarshalled(name, bufferName, bufferLayout, entityCache, initialEntities, requiresReadBack)\n              : undefined;\n          if (bufferResource === undefined) {\n            throw Error(`Unrecognized buffer type ${structType}`);\n          }\n          if (Array.isArray(bufferResource)) {\n            const [buffer, mutator] = bufferResource;\n            buffers[bufferName] = buffer;\n            entityMutators.push(mutator);\n          } else {\n            buffers[bufferName] = bufferResource;\n          }\n        }\n      }\n    }\n    return {\n      buffers,\n      instanceCount: () => entityCache.count(),\n      update(device, queue, encoder) {\n        if (uniformCache.isDirty()) {\n          logFuncs.lazyTrace(LOGGER, () => 'Uniform cache is dirty, mutating uniform');\n          const uniform = uniformCache.get();\n          uniformMutators.forEach((uniformMutator) => uniformMutator.mutate(uniform));\n        }\n        if (entityCache.isDirty()) {\n          logFuncs.lazyTrace(LOGGER, () => 'Entity cache is dirty, mutating entities');\n          const changes = entityCache.calculateChanges();\n          entityMutators.forEach((entityMutator) => entityMutator.mutate(changes));\n        }\n        Object.values(buffers).forEach(buffer => buffer.update(device, queue, encoder));\n      },\n    };\n  },\n  ofUniform: <TUniform>(name: string, bufferName: string, bufferLayout: WPKBufferLayoutUniform<TUniform>, uniformCache: WPKUniformCache<TUniform, any>, requiresReadBack: boolean): WPKResource<WPKTrackedBuffer> | [WPKResource<WPKTrackedBuffer>, WPKMutator<TUniform>] => {\n    const label = toBufferLabel(name, bufferName);\n    logFuncs.lazyDebug(LOGGER, () => `Creating uniform buffer resource for ${label} layout ${JSON.stringify(bufferLayout)}`);\n    const { entries, stride, usage } = bufferLayout;\n    const marshaller = marshallerFactory.ofLayoutEntries(entries, stride);\n    if (uniformCache.isMutable) {\n      logFuncs.lazyTrace(LOGGER, () => `Buffer resources ${label} is mutable`);\n      const buffer = bufferFactory.ofMutable(stride, label, usage, requiresReadBack);\n      const uniformMutator: WPKMutator<TUniform> = {\n        mutate(input) {\n          logFuncs.lazyTrace(LOGGER, () => `Mutating uniform buffer ${label} with new data ${JSON.stringify(input)}`);\n          const data = marshaller.encode([input]);\n          buffer.mutate(data, 0);\n        },\n      };\n      return [buffer, uniformMutator];\n    } else {\n      logFuncs.lazyTrace(LOGGER, () => `Buffer resources ${label} is not mutable`);\n      const input = uniformCache.get();\n      logFuncs.lazyTrace(LOGGER, () => `Creating uniform buffer ${label} with initial data ${JSON.stringify(input)}`);\n      const data = marshaller.encode([input]);\n      const buffer = bufferFactory.ofData(data, label, usage, requiresReadBack);\n      return buffer;\n    }\n  },\n  ofEditable: <TEntity>(name: string, bufferName: string, bufferLayout: WPKBufferLayoutEditable, entityCache: WPKEntityCache<TEntity, any, any>, requiresReadBack: boolean): WPKResource<WPKTrackedBuffer> | [WPKResource<WPKTrackedBuffer>, WPKMutator<ValueSlices<TEntity[]>>] => {\n    const label = toBufferLabel(name, bufferName);\n    logFuncs.lazyDebug(LOGGER, () => `Create editable buffer resource for ${label} layout ${JSON.stringify(bufferLayout)}`);\n    const { stride, usage } = bufferLayout;\n    if (entityCache.isResizeable) {\n      logFuncs.lazyTrace(LOGGER, () => `Creating resizeable buffer ${label} with stride ${stride}`);\n      const buffer = bufferFactory.ofResizeable(false, label, usage, requiresReadBack);\n      let maxInstanceCount = 0;\n      const entityMutator: WPKMutator<ValueSlices<TEntity[]>> = {\n        mutate(input) {\n          const { copySlices } = input;\n          logFuncs.lazyTrace(LOGGER, () => `Mutating resizeable buffer ${label} with input ${JSON.stringify(input)}`);\n          const maxCopySliceIndex = copySlices.reduce((max, copySlice) => Math.max(max, copySlice.toIndex + copySlice.length), 0);\n          maxInstanceCount = Math.max(maxInstanceCount, maxCopySliceIndex + 1);\n          const bytesLength = maxInstanceCount * stride;\n          logFuncs.lazyTrace(LOGGER, () => `Resizing buffer ${label} to desired bytes length ${bytesLength}`);\n          buffer.resize(bytesLength);\n        },\n      };\n      return [buffer, entityMutator];\n    } else {\n      logFuncs.lazyTrace(LOGGER, () => `Creating fixed size buffer ${label} with stride ${stride}`);\n      return bufferFactory.ofSize(entityCache.count() * stride, label, usage, requiresReadBack);\n    }\n  },\n  ofMarshalled: <TEntity>(name: string, bufferName: string, bufferLayout: WPKBufferLayoutMarshalled<TEntity>, entityCache: WPKEntityCache<TEntity, any, any>, initialEntities: TEntity[], requiresReadBack: boolean): WPKResource<WPKTrackedBuffer> | [WPKResource<WPKTrackedBuffer>, WPKMutator<ValueSlices<TEntity[]>>] => {\n    const label = toBufferLabel(name, bufferName);\n    logFuncs.lazyDebug(LOGGER, () => `Create marshalled buffer resource for ${label} layout ${JSON.stringify(bufferLayout)}`);\n    const { entries, stride, usage } = bufferLayout;\n    if (entityCache.isMutable || entityCache.isResizeable) {\n      const buffer = bufferFactory.ofStaged(label, usage, requiresReadBack);\n      logFuncs.lazyTrace(LOGGER, () => `Buffer resource ${label} has stride ${stride}`);\n      const marshaller = marshallerFactory.ofLayoutEntries(entries, stride);\n      const entityMutator: WPKMutator<ValueSlices<TEntity[]>> = {\n        mutate(input) {\n          logFuncs.lazyTrace(LOGGER, () => `Mutating buffer ${label} ${input.values.length} entities with slices ${JSON.stringify(input.copySlices)}`);\n          const { copySlices, values } = input;\n          const data = marshaller.encode(values);\n          const targetSlices = copySlices.map((copySlice): CopySlice => {\n            return {\n              length: copySlice.length * stride,\n              min: copySlice.min * stride,\n              toIndex: copySlice.toIndex * stride,\n            };\n          });\n          logFuncs.lazyTrace(LOGGER, () => `Mutating buffer ${label} with ${data.byteLength} bytes with target slices ${JSON.stringify(targetSlices)}`);\n          buffer.mutate(data, targetSlices);\n        },\n      };\n      return [buffer, entityMutator];\n    } else {\n      logFuncs.lazyTrace(LOGGER, () => `Buffer resource ${label} is constant`);\n      const marshaller = marshallerFactory.ofLayoutEntries(entries, stride);\n      const data = marshaller.encode(initialEntities);\n      logFuncs.lazyTrace(LOGGER, () => `Create buffer resource ${label} with data ${JSON.stringify(data)}`);\n      return bufferFactory.ofData(data, label, usage, requiresReadBack);\n    }\n  },\n};\n\nconst toBufferLabel = (name: string, bufferName: string): string => `${name}-buffer-${bufferName}`;\n","import { getLogger } from './logging';\nimport { WPKComputePass, WPKDispatchParamsDetail, WPKDispatchCount, WPKDispatchCounts, WPKWorkGroupSize } from './types';\nimport { logFuncs } from './utils';\n\nconst LOGGER = getLogger('pipeline');\n\nconst VERTEX_FORMAT_BYTE_LENGTHS: Record<GPUVertexFormat, number> = {\n  float16: 2 * 1,\n  float16x2: 2 * 2,\n  float16x4: 2 * 4,\n  float32: 4 * 1,\n  float32x2: 4 * 2,\n  float32x3: 4 * 3,\n  float32x4: 4 * 4,\n  sint8: 1 * 1,\n  sint8x2: 1 * 2,\n  sint8x4: 1 * 4,\n  sint16: 2 * 1,\n  sint16x2: 2 * 2,\n  sint16x4: 2 * 4,\n  sint32: 4 * 1,\n  sint32x2: 4 * 2,\n  sint32x3: 4 * 3,\n  sint32x4: 4 * 4,\n  snorm8: 1 * 1,\n  snorm8x2: 1 * 2,\n  snorm8x4: 1 * 4,\n  snorm16: 2 * 1,\n  snorm16x2: 2 * 2,\n  snorm16x4: 2 * 4,\n  uint8: 1 * 1,\n  uint8x2: 1 * 2,\n  uint8x4: 1 * 4,\n  uint16: 2 * 1,\n  uint16x2: 2 * 2,\n  uint16x4: 2 * 4,\n  uint32: 4 * 1,\n  uint32x2: 4 * 2,\n  uint32x3: 4 * 3,\n  uint32x4: 4 * 4,\n  unorm8: 1 * 1,\n  unorm8x2: 1 * 2,\n  unorm8x4: 1 * 4,\n  unorm16: 2 * 1,\n  unorm16x2: 2 * 2,\n  unorm16x4: 2 * 4,\n  'unorm8x4-bgra': 1 * 4,\n  'unorm10-10-10-2': 10 + 10 + 10 + 2,\n};\n\nexport const pipelineFuncs = {\n  ANTI_ALIASED_SAMPLE_COUNT: 4,\n  toByteLength: (format: GPUVertexFormat): number => {\n    return VERTEX_FORMAT_BYTE_LENGTHS[format];\n  },\n  toByteLengthTotal: (formats: GPUVertexFormat[]): number => {\n    return formats.reduce((currentByteLength, format) => currentByteLength + pipelineFuncs.toByteLength(format), 0);\n  },\n  toDispatchParams: (passes: WPKComputePass<any, any, any>[], instanceCount: number): WPKDispatchParamsDetail<any> => {\n    return {\n      instanceCount,\n      dispatchCounts: passes.reduce((acc, pass) => {\n        acc[pass.entryPoint] = pipelineFuncs.toDispatchCount(instanceCount, pass.workGroupSize);\n        return acc;\n      }, {} as WPKDispatchCounts<any>),\n    };\n  },\n  toDispatchCount: (instanceCount: number, workGroupSize: WPKWorkGroupSize): WPKDispatchCount => {\n    const totalThreads = workGroupSize.x * (workGroupSize.y || 1) * (workGroupSize.z || 1);\n    const x = Math.ceil(instanceCount / totalThreads);\n    return [x, 1, 1]; // TODO test with y and z\n  },\n  getContext: (canvas: HTMLCanvasElement): GPUCanvasContext => {\n    logFuncs.lazyTrace(LOGGER, () => 'Get webgpu context from canvas');\n    const context = canvas.getContext('webgpu');\n    if (context === null) {\n      throw Error('Failed to get WebGPU context from canvas');\n    }\n    return context;\n  },\n  getGpu: (): GPU => {\n    logFuncs.lazyTrace(LOGGER, () => 'Get gpu from navigator');\n    const { gpu } = navigator;\n    if (gpu === undefined) {\n      throw Error('WebGPU not supported in this browser');\n    }\n    return gpu;\n  },\n  getFormat: (gpu: GPU): GPUTextureFormat => {\n    logFuncs.lazyTrace(LOGGER, () => 'Get format from gpu');\n    return gpu.getPreferredCanvasFormat();\n  },\n  getDevice: async (gpu: GPU): Promise<GPUDevice> => {\n    logFuncs.lazyTrace(LOGGER, () => 'Get adapter from gpu');\n    const adapter = await gpu.requestAdapter();\n    if (adapter === null) {\n      throw Error('Failed to request GPU adapter');\n    }\n    logFuncs.lazyTrace(LOGGER, () => 'Get device from adapter');\n    return await adapter.requestDevice();\n  },\n};\n","import { getLogger } from './logging';\nimport { meshFuncs } from './mesh-factories';\nimport { pipelineFuncs } from './pipeline-utils';\nimport { resourceFactory } from './resources';\nimport { WPKBindGroupDetail, WPKBindGroupsDetail, WPKBindingIndex, WPKBufferFormatKey, WPKBufferFormatMap, WPKBufferResources, WPKComputePass, WPKComputePipelineDetail, WPKDispatchParamsDetail, WPKDispatchCount, WPKDrawCounts, WPKGroupIndex, WPKMesh, WPKMeshBufferResource, WPKRenderPipelineDetail, WPKResource, WPKShaderModuleDetail, WPKTrackedBuffer, WPKVertexBufferAttributeData, WPKVertexBufferDetail } from './types';\nimport { logFuncs } from './utils';\n\nconst LOGGER = getLogger('resources');\n\nexport const pipelineResourceFactory = {\n  // layouts\n  ofBindGroupLayout: (\n    name: string,\n    entries: GPUBindGroupLayoutEntry[]\n  ): WPKResource<GPUBindGroupLayout> => {\n    const label = `${name}-bind-group-layout`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating bind group layout resource ${label}`);\n    let layout: GPUBindGroupLayout | undefined;\n    return resourceFactory.ofCached({\n      update(device, _queue, _encoder) {\n        logFuncs.lazyTrace(LOGGER, () => `Creating bind group layout ${label}`);\n        layout = device.createBindGroupLayout({\n          label,\n          entries,\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created bind group layout ${JSON.stringify(layout)}`);\n      },\n      get() {\n        return resourceFactory.getOrThrow(layout, `bind group layout ${label}`);\n      },\n      clean() {\n      },\n    });\n  },\n  ofPipelineLayout: (\n    name: string,\n    bindGroupLayoutsResource: WPKResource<GPUBindGroupLayout[]>\n  ): WPKResource<GPUPipelineLayout> => {\n    const label = `${name}-pipeline-layout`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating pipeline layout resource ${label}`);\n    let layout: GPUPipelineLayout | undefined;\n    return resourceFactory.ofCached({\n      update(device, queue, encoder) {\n        bindGroupLayoutsResource.update(device, queue, encoder);\n        const bindGroupLayouts = bindGroupLayoutsResource.get();\n        logFuncs.lazyTrace(LOGGER, () => `Creating pipeline layout ${label} from ${bindGroupLayouts.length} bind group layouts [${bindGroupLayouts.map(l => l.label).join(', ')}]`);\n        layout = device.createPipelineLayout({\n          label,\n          bindGroupLayouts,\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created pipeline layout ${JSON.stringify(layout)}`);\n      },\n      get() {\n        return resourceFactory.getOrThrow(layout, `pipeline layout ${label}`);\n      },\n      clean() {\n        bindGroupLayoutsResource.clean();\n      },\n    });\n  },\n\n  // shader\n  ofShaderModule: (\n    name: string,\n    shaderModule: WPKShaderModuleDetail,\n    pipelineLayoutResource: WPKResource<GPUPipelineLayout>\n  ): WPKResource<GPUShaderModule> => {\n    const label = `${name}-shader`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating shader module resource ${label}`);\n    const { code, entryPoints } = shaderModule;\n    return resourceFactory.ofCachedFromDependencies(\n      [pipelineLayoutResource],\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating shader module ${label}`);\n        const module = device.createShaderModule({\n          label,\n          code,\n          compilationHints: entryPoints.map((entryPoint) => ({\n            entryPoint,\n            layout: values[0],\n          })),\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created shader module ${JSON.stringify(module)}`);\n        return module;\n      },\n    );\n  },\n\n  // bind groups\n  ofBindGroupEntry: (\n    binding: WPKBindingIndex,\n    bufferResource: WPKResource<WPKTrackedBuffer>\n  ): WPKResource<GPUBindGroupEntry> => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating bind group entry resource binding ${binding}`);\n    return resourceFactory.ofCachedFromDependencies(\n      [bufferResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating bind group entry binding ${binding}`);\n        const entry = {\n          binding,\n          resource: {\n            buffer: values[0].buffer,\n          },\n        };\n        logFuncs.lazyTrace(LOGGER, () => `Created bind group entry ${JSON.stringify({ ...entry, buffer: entry.resource.buffer.label, })}`);\n        return entry;\n      },\n    );\n  },\n  ofBindGroup: (\n    name: string,\n    bindGroupLayoutResource: WPKResource<GPUBindGroupLayout>,\n    bindGroupEntriesResource: WPKResource<GPUBindGroupEntry[]>\n  ): WPKResource<GPUBindGroup> => {\n    const label = `${name}-bind-group`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating bind group resource ${label}`);\n    return resourceFactory.ofCachedFromDependencies(\n      [bindGroupLayoutResource, bindGroupEntriesResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating bind group ${label}`);\n        const group = device.createBindGroup({\n          label,\n          layout: values[0],\n          entries: values[1],\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created bind group ${JSON.stringify(group)}`);\n        return group;\n      },\n    );\n  },\n  ofBindGroupDetail: (\n    group: WPKGroupIndex,\n    bindGroupResource: WPKResource<GPUBindGroup>,\n  ): WPKResource<WPKBindGroupDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating bind group detail group index ${group}`);\n    return resourceFactory.ofCachedFromDependencies(\n      [bindGroupResource],\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating bind group detail group index ${group}`);\n        const detail = {\n          group: values[0],\n          index: group,\n        };\n        logFuncs.lazyTrace(LOGGER, () => `Created bind group detail ${JSON.stringify(detail)}`);\n        return detail;\n      },\n    );\n  },\n\n  // compute\n  ofComputePipeline: (\n    name: string,\n    index: number,\n    pipelineLayoutResource: WPKResource<GPUPipelineLayout>,\n    shaderResource: WPKResource<GPUShaderModule>,\n    entryPoint: string\n  ): WPKResource<GPUComputePipeline> => {\n    const label = `${name}-compute-pipeline-${index}`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating compute pipeline resource ${label}`);\n    return resourceFactory.ofCachedFromDependencies(\n      [pipelineLayoutResource, shaderResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating compute pipeline ${label}`);\n        const pipeline = device.createComputePipeline({\n          label,\n          layout: values[0],\n          compute: {\n            module: values[1],\n            entryPoint,\n          },\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created compute pipeline ${JSON.stringify(pipeline)}`);\n        return pipeline;\n      },\n    );\n  },\n  ofComputeDetail: (\n    bindGroupsResource: WPKResource<WPKBindGroupsDetail>,\n    computePipelineResource: WPKResource<GPUComputePipeline>,\n    dispatchCountResource: WPKResource<WPKDispatchCount>,\n  ): WPKResource<WPKComputePipelineDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating compute detail resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [bindGroupsResource, computePipelineResource, dispatchCountResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating compute detail');\n        const detail = {\n          bindGroups: values[0],\n          pipeline: values[1],\n          dispatchCount: values[2],\n        };\n        logFuncs.lazyTrace(LOGGER, () => `Created compute detail ${JSON.stringify(detail)}`);\n        return detail;\n      },\n    );\n  },\n  ofDispatchParams: (\n    instanceCountResource: WPKResource<number>,\n    passes: WPKComputePass<any, any, any>[],\n  ): WPKResource<WPKDispatchParamsDetail<any>> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating dispatch params resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [instanceCountResource] as const,\n      (_device, _queue, _encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating dispatch params resource');\n        const params = pipelineFuncs.toDispatchParams(passes, values[0]);\n        logFuncs.lazyTrace(LOGGER, () => `Created dispatch params ${JSON.stringify(params)}`);\n        return params;\n      }\n    );\n  },\n  ofDispatchCount: (\n    dispatchParamsResource: WPKResource<WPKDispatchParamsDetail<any>>,\n    entryPoint: string,\n  ): WPKResource<WPKDispatchCount> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating dispatch size resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [dispatchParamsResource] as const,\n      (_device, _queue, _encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating dispatch size for ${entryPoint}`);\n        const count = values[0].dispatchCounts[entryPoint];\n        logFuncs.lazyTrace(LOGGER, () => `Created dispatch size ${JSON.stringify(count)}`);\n        return count;\n      }\n    );\n  },\n\n  // render\n  ofVertexBufferDetailMesh: (\n    meshBufferLocation: number,\n    meshBufferResource: WPKMeshBufferResource\n  ): WPKResource<WPKVertexBufferDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating vertex buffer detail resource from mesh');\n    const format: GPUVertexFormat = 'float32x3';\n    const arrayStride = pipelineFuncs.toByteLength(format);\n    const attributes: GPUVertexAttribute[] = [{\n      format,\n      offset: 0,\n      shaderLocation: meshBufferLocation,\n    }];\n    const detail = pipelineResourceFactory.ofVertexBufferDetail(arrayStride, attributes, 'vertex', meshBufferResource.vertices);\n    logFuncs.lazyTrace(LOGGER, () => `Created vertex buffer detail resource ${JSON.stringify(detail)}`);\n    return detail;\n  },\n  ofVertexBufferDetailBufferLocationFieldTypes: <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>(\n    vertexBufferLocationFieldTypes: WPKVertexBufferAttributeData<TUniform, TEntity, TBufferFormatMap>,\n    bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>\n  ): WPKResource<WPKVertexBufferDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => `Creating vertex buffer detail resource from buffer location field types ${JSON.stringify(vertexBufferLocationFieldTypes)}`);\n    const { buffer, locationAttributes, stride } = vertexBufferLocationFieldTypes;\n    const bufferResource = bufferResources.buffers[buffer as WPKBufferFormatKey<TUniform, TEntity, TBufferFormatMap, any, any>];\n    const attributes = locationAttributes.map(attribute => attribute.attribute);\n    const detail = pipelineResourceFactory.ofVertexBufferDetail(stride, attributes, 'instance', bufferResource);\n    logFuncs.lazyTrace(LOGGER, () => `Created vertex buffer detail resource ${JSON.stringify(detail)}`);\n    return detail;\n  },\n  ofVertexBufferDetail: (\n    arrayStride: number,\n    attributes: GPUVertexAttribute[],\n    step: GPUVertexStepMode,\n    bufferResource: WPKResource<WPKTrackedBuffer>\n  ): WPKResource<WPKVertexBufferDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating vertex buffer detail resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [bufferResource] as const,\n      (_device, _queue, _encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating vertex buffer detail');\n        const detail = {\n          buffer: values[0].buffer,\n          layout: {\n            arrayStride,\n            attributes,\n            stepMode: step,\n          },\n        };\n        logFuncs.lazyTrace(LOGGER, () => `Created vertex buffer detail ${JSON.stringify({ ...detail, buffer: detail.buffer.label, })}`);\n        return detail;\n      },\n    );\n  },\n  ofVertexBuffers: (\n    vertexBufferDetailResources: WPKResource<WPKVertexBufferDetail>[]\n  ): WPKResource<GPUBuffer[]> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating vertex buffers resource');\n    return resourceFactory.ofCachedFromDependencies(\n      vertexBufferDetailResources,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating vertex buffers');\n        const buffers = values.map((data) => data.buffer);\n        logFuncs.lazyTrace(LOGGER, () => `Created vertex buffers ${JSON.stringify(buffers.map(b => b.label))}`);\n        return buffers;\n      },\n    );\n  },\n  ofVertexBufferLayouts: (\n    vertexBufferDetailsResource: WPKResource<WPKVertexBufferDetail[]>\n  ): WPKResource<GPUVertexBufferLayout[]> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating vertex buffer layouts resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [vertexBufferDetailsResource] as const,\n      (_device, _queue, _encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating vertex buffer layouts');\n        const layouts = values[0].map((data) => data.layout);\n        logFuncs.lazyTrace(LOGGER, () => `Created vertex buffer layouts ${JSON.stringify(layouts)}`);\n        return layouts;\n      },\n    );\n  },\n  ofRenderPipeline: (\n    name: string,\n    index: number,\n    mesh: WPKMesh,\n    shaderModuleResource: WPKResource<GPUShaderModule>,\n    vertexShaderEntryPoint: string,\n    fragmentShaderEntryPoint: string,\n    vertexBufferLayoutsResource: WPKResource<GPUVertexBufferLayout[]>,\n    renderPipelineLayoutResource: WPKResource<GPUPipelineLayout>,\n  ): WPKResource<GPURenderPipeline> => {\n    const label = `${name}-render-pipeline-${index}`;\n    logFuncs.lazyDebug(LOGGER, () => `Creating render pipeline resource ${label}`);\n    const topology = mesh.topology;\n    const frontFace = mesh.winding;\n    const cullMode = meshFuncs.cullMode(mesh);\n    const gpu = pipelineFuncs.getGpu();\n    const format = pipelineFuncs.getFormat(gpu);\n    return resourceFactory.ofCachedFromDependencies(\n      [renderPipelineLayoutResource, shaderModuleResource, vertexBufferLayoutsResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => `Creating render pipeline ${label}`);\n        const pipeline = device.createRenderPipeline({\n          label,\n          layout: values[0],\n          vertex: {\n            module: values[1],\n            entryPoint: vertexShaderEntryPoint,\n            buffers: values[2],\n          },\n          fragment: {\n            module: values[1],\n            entryPoint: fragmentShaderEntryPoint,\n            targets: [{\n              format,\n            }],\n          },\n          multisample: {\n            count: pipelineFuncs.ANTI_ALIASED_SAMPLE_COUNT,\n          },\n          primitive: {\n            topology,\n            frontFace,\n            cullMode,\n          },\n        });\n        logFuncs.lazyTrace(LOGGER, () => `Created render pipeline ${pipeline}`);\n        return pipeline;\n      },\n    );\n  },\n  ofRenderPipelineDetail: (\n    indicesType: GPUIndexFormat,\n    bindGroupsDetailResource: WPKResource<WPKBindGroupsDetail>,\n    indicesBufferResource: WPKResource<GPUBuffer>,\n    vertexBuffersResource: WPKResource<GPUBuffer[]>,\n    renderPipelineResource: WPKResource<GPURenderPipeline>,\n    drawCountsFunc: () => WPKDrawCounts,\n  ): WPKResource<WPKRenderPipelineDetail> => {\n    logFuncs.lazyDebug(LOGGER, () => 'Creating render pipeline detail resource');\n    return resourceFactory.ofCachedFromDependencies(\n      [bindGroupsDetailResource, indicesBufferResource, vertexBuffersResource, renderPipelineResource] as const,\n      (device, queue, encoder, values) => {\n        logFuncs.lazyTrace(LOGGER, () => 'Creating render pipeline detail');\n        const detail = {\n          bindGroups: values[0],\n          indices: {\n            buffer: values[1],\n            format: indicesType,\n          },\n          vertexBuffers: values[2],\n          pipeline: values[3],\n          drawCountsFunc,\n        };\n        logFuncs.lazyTrace(LOGGER, () => `Created render pipeline detail ${JSON.stringify({ ...detail, vertexBuffers: detail.vertexBuffers.map(b => b.label), })}`);\n        return detail;\n      }\n    );\n  },\n};\n","export enum WPKPeripheralEventType {\n  KEY_DOWN = 'key-down',\n  KEY_PRESS = 'key-press',\n  KEY_UP = 'key-up',\n  MOUSE_DOWN = 'mouse-down',\n  MOUSE_DRAG = 'mouse-drag',\n  MOUSE_UP = 'mouse-up',\n  MOUSE_MOVE = 'mouse-move',\n  SCREEN_RESIZE = 'screen-resize',\n};\nexport type WPKPeripheralEventInfoTypeMap = {\n  [WPKPeripheralEventType.KEY_DOWN]: WPKKeyEventInfo,\n  [WPKPeripheralEventType.KEY_PRESS]: WPKKeyEventInfo,\n  [WPKPeripheralEventType.KEY_UP]: WPKKeyEventInfo,\n  [WPKPeripheralEventType.MOUSE_DOWN]: WPKMouseButtonEventInfo,\n  [WPKPeripheralEventType.MOUSE_DRAG]: WPKMouseDragEventInfo,\n  [WPKPeripheralEventType.MOUSE_UP]: WPKMouseButtonEventInfo,\n  [WPKPeripheralEventType.MOUSE_MOVE]: WPKMouseMoveEventInfo,\n  [WPKPeripheralEventType.SCREEN_RESIZE]: WPKScreenEventInfo,\n};\nexport enum WPKMouseButton {\n  LEFT = 'left',\n  MIDDLE = 'middle',\n  RIGHT = 'right',\n  BACK = 'back',\n  FORWARD = 'forward',\n};\ntype WPKKeyModifiers = {\n  alt: boolean;\n  ctrl: boolean;\n  meta: boolean;\n  shift: boolean;\n};\nexport type WPKScreenXY = {\n  normalized: {\n    x: number;\n    y: number;\n  };\n  absolute: {\n    x: number;\n    y: number;\n  };\n};\ntype WPKPeripheralEventBase = {\n  timestamp: number;\n};\nexport type WPKKeyEventInfo = WPKPeripheralEventBase & {\n  key: string;\n  code: string;\n  isRepeat: boolean;\n  modifiers: WPKKeyModifiers;\n};\ntype WPKMouseEventInfoBase = WPKPeripheralEventBase & {\n  position: WPKScreenXY;\n};\nexport type WPKMouseButtonEventInfo = WPKMouseEventInfoBase & {\n  trigger: WPKMouseButton;\n  pressed: WPKMouseButton[];\n  repeatCount: number;\n};\nexport type WPKMouseMoveEventInfo = WPKMouseEventInfoBase & {\n};\nexport type WPKMouseDragEventInfo = WPKMouseButtonEventInfo & WPKMouseMoveEventInfo & {\n  drag: WPKScreenXY;\n};\nexport type WPKScreenEventInfo = WPKPeripheralEventBase & {\n  width: number;\n  height: number;\n  aspectRatio: number;\n};\n\nexport type WPKPeripheralEventHandler<TEvent extends keyof WPKPeripheralEventInfoTypeMap> = (eventInfo: WPKPeripheralEventInfoTypeMap[TEvent]) => any;\nexport type WPKPeripheralEventHandlers = {\n  [E in keyof WPKPeripheralEventInfoTypeMap]?: WPKPeripheralEventHandler<E>;\n};\nexport type WPKEventListenerRemover = {\n  remove: () => void;\n};\n","import { bufferFactory } from './buffer-factory';\nimport { bufferFormatFuncs } from './buffer-formats';\nimport { bufferLayoutsFuncs } from './buffer-layout';\nimport { bufferResourcesFactory } from './buffer-resources';\nimport { cacheFactory } from './cache';\nimport { datumExtractEmbedFactory } from './datum-extract-embed';\nimport { getLogger } from './logging';\nimport { meshFuncs } from './mesh-factories';\nimport { pipelineResourceFactory } from './pipeline-resources';\nimport { resourceFactory } from './resources';\nimport { toCodeShaderCompute, toCodeShaderRender } from './shader-code';\nimport { shaderReserved } from './shader-reserved';\nimport { shaderFuncs } from './shader-utils';\nimport { WPKBindGroupDetail, WPKBindGroupsDetail, WPKReadBackContentMap, WPKBufferFormatKey, WPKBufferFormatMap, WPKBufferResizeable, WPKBufferResources, WPKComputePipelineDetail, WPKReadBackFuncs, WPKReadBackOptions, WPKDrawCounts, WPKEntityCache, WPKGroupBinding, WPKGroupIndex, WPKMeshTemplateMap, WPKPipeline, WPKPipelineDetail, WPKPipelineOptions, WPKRenderPipelineDetail, WPKResource, WPKComputeShader, WPKRenderShader, WPKTrackedBuffer, WPKUniformCache, WPKVertexBufferDetail, WPKDispatchResource, WPKBufferLayouts, WPKBufferLayout, WPKStructType } from './types';\nimport { logFuncs } from './utils';\n\nconst PIPELINE_LOGGER = getLogger('pipeline');\nconst BUFFER_LOGGER = getLogger('buffer');\n\nexport const pipelineFactory = {\n  ofCompute: <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMutableUniform extends boolean, TMutableEntities extends boolean, TResizeableEntities extends boolean>(\n    name: string,\n    bufferFormats: TBufferFormatMap,\n    shader: WPKComputeShader<TUniform, TEntity, TBufferFormatMap>,\n    options: WPKPipelineOptions<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>,\n    readBackOptions: WPKReadBackOptions<TUniform, TEntity, TBufferFormatMap> = {},\n  ): WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities> => {\n    checkNotUsingReservedBufferFormats(bufferFormats);\n    const uniformCache = cacheFactory.ofUniform(options.mutableUniform, options.initialUniform);\n    const entityCache = toEntityCache(options, bufferFormats);\n    const bufferLayouts = bufferLayoutsFuncs.toBufferLayouts<TUniform, TEntity, TBufferFormatMap>(bufferFormats, entityCache, isBufferBound(shader.groupBindings), () => false);\n    const requiresReadBack = readBackOptions.onReadBack !== undefined;\n    const bufferResources = bufferResourcesFactory.ofBufferLayouts<TUniform, TEntity, TBufferFormatMap>(name, uniformCache, entityCache, bufferLayouts, requiresReadBack);\n    const dispatchResource = toComputeDispatchResource(name, shader, bufferResources.instanceCount, requiresReadBack);\n    const computePipelineDetailsResource = toComputePipelineDetailsResource<TUniform, TEntity, TBufferFormatMap>(name, shader, bufferLayouts, bufferResources, dispatchResource);\n    const readBackFuncResource = toReadBackFuncResource(bufferLayouts, bufferResources, dispatchResource, entityCache, readBackOptions);\n    const pipelineDetailResource = toPipelineDetailResource(name, bufferResources, computePipelineDetailsResource, undefined, readBackFuncResource);\n    const pipeline: WPKPipeline<any, any, any, any, any> = {\n      name,\n      pipelineDetail(device, queue, encoder) {\n        logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Create pipeline detail');\n        pipelineDetailResource.update(device, queue, encoder);\n        return pipelineDetailResource.get();\n      },\n      clean() {\n        pipelineDetailResource.clean();\n      },\n    };\n    addPipelineOptions(pipeline, options, uniformCache, entityCache);\n    return pipeline as WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>;\n  },\n  ofComputeRender: <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMeshTemplateMap extends WPKMeshTemplateMap, TMutableUniform extends boolean, TMutableEntities extends boolean, TResizeableEntities extends boolean>(\n    name: string,\n    bufferFormats: TBufferFormatMap,\n    meshTemplates: TMeshTemplateMap,\n    computeShader: WPKComputeShader<TUniform, TEntity, TBufferFormatMap>,\n    renderShader: WPKRenderShader<TUniform, TEntity, TBufferFormatMap, TMeshTemplateMap, any>,\n    options: WPKPipelineOptions<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>,\n    readBackOptions: WPKReadBackOptions<TUniform, TEntity, TBufferFormatMap> = {},\n  ): WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities> => {\n    checkNotUsingReservedBufferFormats(bufferFormats);\n    const uniformCache = cacheFactory.ofUniform(options.mutableUniform, options.initialUniform);\n    const entityCache = toEntityCache(options, bufferFormats);\n    const bufferLayouts = bufferLayoutsFuncs.toBufferLayouts<TUniform, TEntity, TBufferFormatMap>(bufferFormats, entityCache, isBufferBound(computeShader.groupBindings, renderShader.groupBindings), isVertexBuffer(renderShader));\n    const requiresReadBack = readBackOptions.onReadBack !== undefined;\n    const bufferResources = bufferResourcesFactory.ofBufferLayouts<TUniform, TEntity, TBufferFormatMap>(name, uniformCache, entityCache, bufferLayouts, requiresReadBack);\n    const dispatchResource = toComputeDispatchResource(name, computeShader, bufferResources.instanceCount, requiresReadBack);\n    const computePipelineDetailsResource = toComputePipelineDetailsResource(`${name}-compute`, computeShader, bufferLayouts, bufferResources, dispatchResource);\n    const renderPipelineDetailResource = toRenderPipelineDetailsResource(`${name}-render`, meshTemplates, renderShader, bufferResources.instanceCount, bufferLayouts, bufferResources, requiresReadBack);\n    const readBackFuncResource = toReadBackFuncResource(bufferLayouts, bufferResources, dispatchResource, entityCache, readBackOptions);\n    const pipelineDetailResource = toPipelineDetailResource(name, bufferResources, computePipelineDetailsResource, renderPipelineDetailResource, readBackFuncResource);\n    const pipeline: WPKPipeline<any, any, any, any, any> = {\n      name,\n      pipelineDetail(device, queue, encoder) {\n        logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Create pipeline detail');\n        pipelineDetailResource.update(device, queue, encoder);\n        return pipelineDetailResource.get();\n      },\n      clean() {\n        pipelineDetailResource.clean();\n      },\n    };\n    addPipelineOptions(pipeline, options, uniformCache, entityCache);\n    return pipeline as WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>;\n  },\n  ofRender: <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMeshTemplateMap extends WPKMeshTemplateMap, TMutableUniform extends boolean, TMutableEntities extends boolean, TResizeableEntities extends boolean>(\n    name: string,\n    bufferFormats: TBufferFormatMap,\n    meshTemplates: TMeshTemplateMap,\n    shader: WPKRenderShader<TUniform, TEntity, TBufferFormatMap, TMeshTemplateMap, any>,\n    options: WPKPipelineOptions<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>,\n    readBackOptions: WPKReadBackOptions<TUniform, TEntity, TBufferFormatMap> = {},\n  ): WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities> => {\n    checkNotUsingReservedBufferFormats(bufferFormats);\n    const uniformCache = cacheFactory.ofUniform(options.mutableUniform, options.initialUniform);\n    const entityCache = toEntityCache(options, bufferFormats);\n    const bufferLayouts = bufferLayoutsFuncs.toBufferLayouts<TUniform, TEntity, TBufferFormatMap>(bufferFormats, entityCache, isBufferBound(shader.groupBindings), isVertexBuffer(shader));\n    const requiresReadBack = readBackOptions.onReadBack !== undefined;\n    const bufferResources = bufferResourcesFactory.ofBufferLayouts<TUniform, TEntity, TBufferFormatMap>(name, uniformCache, entityCache, bufferLayouts, requiresReadBack);\n    const renderPipelineDetailResource = toRenderPipelineDetailsResource(name, meshTemplates, shader, bufferResources.instanceCount, bufferLayouts, bufferResources, requiresReadBack);\n    const readBackFuncResource = toReadBackFuncResource(bufferLayouts, bufferResources, undefined, entityCache, readBackOptions);\n    const pipelineDetailResource = toPipelineDetailResource(name, bufferResources, undefined, renderPipelineDetailResource, readBackFuncResource);\n    const pipeline: WPKPipeline<any, any, any, any, any> = {\n      name,\n      pipelineDetail(device, queue, encoder) {\n        logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Create pipeline detail');\n        pipelineDetailResource.update(device, queue, encoder);\n        return pipelineDetailResource.get();\n      },\n      clean() {\n        pipelineDetailResource.clean();\n      },\n    };\n    addPipelineOptions(pipeline, options, uniformCache, entityCache);\n    return pipeline as WPKPipeline<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>;\n  },\n};\n\nconst checkNotUsingReservedBufferFormats = (bufferFormats: WPKBufferFormatMap<any, any>): void => {\n  if (Object.keys(bufferFormats).includes(shaderReserved.DISPATCH_PARAMS_BUFFER_NAME)) {\n    throw Error(`Cannot use reserved buffer format name ${shaderReserved.DISPATCH_PARAMS_BUFFER_NAME}`);\n  }\n};\n\nconst toEntityCache = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMutableEntities extends boolean, TResizeableEntities extends boolean>(\n  options: WPKPipelineOptions<TUniform, TEntity, any, TMutableEntities, TResizeableEntities>,\n  bufferFormats: TBufferFormatMap\n): WPKEntityCache<any, any, any> => {\n  if (options.resizeableEntities) {\n    const entityIndexes = bufferFormatFuncs.findFormatEntityIndexes(bufferFormats);\n    const entityIndexDatumExtractors = entityIndexes.map(userFormat => datumExtractEmbedFactory.ofEntityId(userFormat.entityIdKey).extract);\n    const entityCache = cacheFactory.ofEntitiesResizeable(options.mutableEntities, entityIndexDatumExtractors);\n    options.initialEntities.forEach(entity => entityCache.add(entity));\n    return entityCache;\n  } else {\n    return cacheFactory.ofEntitiesFixedSize(options.mutableEntities, ...options.initialEntities);\n  }\n};\n\nconst isBufferBound = (...groupBindings: Array<WPKGroupBinding<any, any, any, any, any>>[]) =>\n  (bufferName: string): boolean =>\n    groupBindings.some(gbs => gbs.some(gb => gb.buffer === bufferName));\n\nconst isVertexBuffer = (renderShader: WPKRenderShader<any, any, any, any, any>) =>\n  (bufferName: string): boolean =>\n    renderShader.passes.some(pass => pass.vertex.vertexBuffers.some(vertexBuffer => vertexBuffer.buffer === bufferName));\n\nconst toPipelineDetailResource = (\n  name: string,\n  bufferResources: WPKBufferResources<any, any, any>,\n  computePipelineDetailsResource: WPKResource<WPKComputePipelineDetail[]> | undefined,\n  renderPipelineDetailResource: WPKResource<WPKRenderPipelineDetail[]> | undefined,\n  readBackFuncResource: WPKResource<WPKReadBackFuncs> | undefined,\n): WPKResource<WPKPipelineDetail> => {\n  let pipelineDetail: WPKPipelineDetail | undefined;\n  const resource: WPKResource<WPKPipelineDetail> = {\n    update(device, queue, encoder) {\n      logFuncs.lazyTrace(PIPELINE_LOGGER, () => `Creating pipeline details ${name}`);\n      bufferResources.update(device, queue, encoder);\n      const instanceCount = bufferResources.instanceCount();\n      pipelineDetail = {\n        name,\n        instanceCount,\n      };\n      if (instanceCount > 0) {\n        if (computePipelineDetailsResource !== undefined) {\n          logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Update compute pipeline');\n          computePipelineDetailsResource.update(device, queue, encoder);\n          pipelineDetail.compute = computePipelineDetailsResource.get();\n        }\n        if (renderPipelineDetailResource !== undefined) {\n          logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Update render pipeline');\n          renderPipelineDetailResource.update(device, queue, encoder);\n          pipelineDetail.render = renderPipelineDetailResource.get();\n        }\n        if (readBackFuncResource !== undefined) {\n          logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Update read back func');\n          readBackFuncResource.update(device, queue, encoder);\n          pipelineDetail.readBackFuncs = readBackFuncResource.get();\n        }\n      }\n    },\n    get() {\n      return resourceFactory.getOrThrow(pipelineDetail, `pipeline detail ${name}`);\n    },\n    clean() {\n      computePipelineDetailsResource?.clean();\n      renderPipelineDetailResource?.clean();\n      readBackFuncResource?.clean();\n      Object.values(bufferResources.buffers).forEach(resource => resource.clean());\n    },\n  };\n  return resource;\n};\n\nconst addPipelineOptions = <TUniform, TEntity, TMutableUniform extends boolean, TMutableEntities extends boolean, TResizeableEntities extends boolean>(\n  pipeline: WPKPipeline<any, any, any, any, any>,\n  options: WPKPipelineOptions<TUniform, TEntity, TMutableUniform, TMutableEntities, TResizeableEntities>,\n  uniformCache: WPKUniformCache<TUniform, TMutableUniform>,\n  entityCache: WPKEntityCache<TEntity, TMutableEntities, any>,\n): void => {\n  if (options.mutableUniform) {\n    (pipeline as WPKPipeline<TUniform, any, true, any, any>).mutateUniform = (uniform) => (uniformCache as WPKUniformCache<TUniform, true>).mutate(uniform);\n  }\n  if (options.mutableEntities) {\n    if (options.resizeableEntities) {\n      (pipeline as WPKPipeline<any, TEntity, any, true, true>).mutateEntityById = (id, entity) => (entityCache as WPKEntityCache<TEntity, true, true>).mutate(id, entity);\n    } else {\n      (pipeline as WPKPipeline<any, TEntity, any, true, false>).mutateEntityByIndex = (index, entity) => (entityCache as WPKEntityCache<TEntity, true, false>).mutate(index, entity);\n    }\n  }\n  if (options.resizeableEntities) {\n    (pipeline as WPKPipeline<any, TEntity, any, any, true>).add = (entity) => (entityCache as WPKEntityCache<TEntity, any, true>).add(entity);\n    (pipeline as WPKPipeline<any, TEntity, any, any, true>).remove = (id) => (entityCache as WPKEntityCache<TEntity, any, true>).remove(id);\n  }\n};\n\nconst toComputeDispatchResource = (\n  name: string,\n  shader: WPKComputeShader<any, any, any>,\n  instanceCountFunc: () => number,\n  requiresReadBack: boolean\n): WPKDispatchResource<any> => {\n  const { passes } = shader;\n  const instanceCountResource = resourceFactory.ofFunc(instanceCountFunc);\n  const params = pipelineResourceFactory.ofDispatchParams(instanceCountResource, passes);\n  const layout = bufferLayoutsFuncs.toBufferLayoutUniform(shaderReserved.DISPATCH_MARSHALLED_FORMAT, GPUBufferUsage.UNIFORM);\n  const buffer = bufferResourcesFactory.ofDispatch(name, layout, params, requiresReadBack);\n  return {\n    layout,\n    buffer,\n    params,\n  };\n};\n\nconst toComputePipelineDetailsResource = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>(\n  name: string,\n  computeShader: WPKComputeShader<TUniform, TEntity, TBufferFormatMap>,\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>,\n  bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>,\n  dispatchResource: WPKDispatchResource<any>,\n): WPKResource<WPKComputePipelineDetail[]> => {\n  const { groupBindings, passes } = computeShader;\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Creating compute pipeline details resource ${name}`);\n  const visibility = GPUShaderStage.COMPUTE;\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Group bindings: ${JSON.stringify(groupBindings)}`);\n  const groupBindingsWithDispatch = [...groupBindings, shaderReserved.DISPATCH_GROUP_BINDING];\n  const bindGroupLayoutsResource = toBindGroupLayoutsResource(name, visibility, groupBindingsWithDispatch, bufferLayouts);\n  const pipelineLayoutResource = pipelineResourceFactory.ofPipelineLayout(name, bindGroupLayoutsResource);\n  const computeShaderModuleDetail = toCodeShaderCompute(computeShader, bufferLayouts);\n  const computeShaderModuleResource = pipelineResourceFactory.ofShaderModule(name, computeShaderModuleDetail, pipelineLayoutResource);\n  const bindGroupsDetailResource = toBindGroupsDetailResource(name, visibility, groupBindingsWithDispatch, bufferLayouts, bufferResources, dispatchResource.buffer);\n  const computePipelineDetailResources: WPKResource<WPKComputePipelineDetail>[] = [];\n  for (const [index, computePass] of passes.entries()) {\n    const { entryPoint } = computePass;\n    const dispatchCountResource = pipelineResourceFactory.ofDispatchCount(dispatchResource.params, entryPoint);\n    const computePipelineResource = pipelineResourceFactory.ofComputePipeline(name, index, pipelineLayoutResource, computeShaderModuleResource, entryPoint);\n    const computeDetailResource = pipelineResourceFactory.ofComputeDetail(bindGroupsDetailResource, computePipelineResource, dispatchCountResource);\n    computePipelineDetailResources.push(computeDetailResource);\n  }\n  return resourceFactory.ofArray(computePipelineDetailResources);\n};\n\nconst toRenderPipelineDetailsResource = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TMeshTemplateMap extends WPKMeshTemplateMap>(\n  name: string,\n  meshTemplateMap: TMeshTemplateMap,\n  renderShader: WPKRenderShader<TUniform, TEntity, TBufferFormatMap, TMeshTemplateMap, any>,\n  instanceCountFunc: () => number,\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>,\n  bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>,\n  requiresReadBack: boolean,\n): WPKResource<WPKRenderPipelineDetail[]> => {\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Creating render pipeline details resource ${name}`);\n  const { groupBindings, passes } = renderShader;\n  const visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT;\n  const bindGroupLayoutsResource = toBindGroupLayoutsResource(name, visibility, groupBindings, bufferLayouts);\n  const pipelineLayoutResource = pipelineResourceFactory.ofPipelineLayout(name, bindGroupLayoutsResource);\n  const renderShaderModuleDetail = toCodeShaderRender(renderShader, bufferLayouts);\n  const renderShaderModuleResource = pipelineResourceFactory.ofShaderModule(name, renderShaderModuleDetail, pipelineLayoutResource);\n  const bindGroupsDetailResource = toBindGroupsDetailResource(name, visibility, groupBindings, bufferLayouts, bufferResources);\n  const renderPipelineDetailResources: WPKResource<WPKRenderPipelineDetail>[] = [];\n  for (const [index, renderPass] of passes.entries()) {\n    const { mesh: { key, parameters }, fragment, vertex } = renderPass;\n    const mesh = meshTemplateMap[key].toMesh(parameters);\n    const indicesCount = meshFuncs.indicesCount(mesh);\n    const indicesType = meshFuncs.indicesType(mesh);\n    const drawCountsFunc = (): WPKDrawCounts => ({\n      indexCount: indicesCount,\n      instanceCount: instanceCountFunc(),\n    });\n    const meshBufferResource = bufferResourcesFactory.ofMesh(name, mesh, requiresReadBack);\n    const indicesBufferResource: WPKResource<GPUBuffer> = {\n      update(device, queue, encoder) {\n        meshBufferResource.indices.update(device, queue, encoder);\n      },\n      get() {\n        return meshBufferResource.indices.get().buffer;\n      },\n      clean() {\n        meshBufferResource.indices.clean();\n      },\n    };\n    const vertexBufferDetailResources: WPKResource<WPKVertexBufferDetail>[] = [];\n    const detailMesh = pipelineResourceFactory.ofVertexBufferDetailMesh(0, meshBufferResource);\n    vertexBufferDetailResources.push(detailMesh);\n    const sortedVertexBufferLocationTypes = shaderFuncs.toVertexBufferAttributeData(vertex.vertexBuffers, bufferLayouts);\n    sortedVertexBufferLocationTypes.forEach((vertexBufferLocationType) => {\n      const detailLocation = pipelineResourceFactory.ofVertexBufferDetailBufferLocationFieldTypes(vertexBufferLocationType, bufferResources);\n      vertexBufferDetailResources.push(detailLocation);\n    });\n    const vertexBufferDetailsResource = resourceFactory.ofArray(vertexBufferDetailResources);\n    const vertexBufferLayoutsResource = pipelineResourceFactory.ofVertexBufferLayouts(vertexBufferDetailsResource);\n    const vertexBuffersResource = pipelineResourceFactory.ofVertexBuffers(vertexBufferDetailResources);\n    const pipelineResource = pipelineResourceFactory.ofRenderPipeline(name, index, mesh, renderShaderModuleResource, vertex.entryPoint, fragment.entryPoint, vertexBufferLayoutsResource, pipelineLayoutResource);\n    const renderPipelineDetailResource = pipelineResourceFactory.ofRenderPipelineDetail(indicesType, bindGroupsDetailResource, indicesBufferResource, vertexBuffersResource, pipelineResource, drawCountsFunc);\n    renderPipelineDetailResources.push(renderPipelineDetailResource);\n  }\n  return resourceFactory.ofArray(renderPipelineDetailResources);\n};\n\nconst toBindGroupLayoutEntries = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TIncludeUniform extends boolean, TIncludeEntity extends boolean>(\n  groupBindings: Array<WPKGroupBinding<TUniform, TEntity, TBufferFormatMap, TIncludeUniform, TIncludeEntity>>,\n  group: WPKGroupIndex,\n  visibility: GPUShaderStageFlags,\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>\n): GPUBindGroupLayoutEntry[] => {\n  PIPELINE_LOGGER.info(`Create bind group layout entries from buffer layouts ${JSON.stringify(bufferLayouts)}`);\n  const entries = groupBindings.filter((groupBinding) => groupBinding.group === group)\n    .map((groupBinding) => {\n      const { binding, buffer } = groupBinding;\n      PIPELINE_LOGGER.info(`group binding ${JSON.stringify(groupBinding)}`);\n      const structType = (buffer === shaderReserved.DISPATCH_PARAMS_BUFFER_NAME)\n        ? 'uniform'\n        : bufferLayouts[buffer].structType;\n      const type = toBufferBindingType(structType, visibility);\n      logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Creating bind group layout entry for group ${group} binding ${binding}`);\n      return {\n        binding,\n        visibility,\n        buffer: {\n          type\n        },\n      };\n    });\n  return entries;\n};\n\nconst toBufferBindingType = (\n  structType: WPKStructType,\n  visibility: GPUShaderStageFlags\n): GPUBufferBindingType => {\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Calculating buffer binding type for buffer type ${JSON.stringify(structType)}`);\n  return structType === 'uniform'\n    ? 'uniform'\n    : (visibility === GPUShaderStage.COMPUTE) && (structType === 'editable')\n      ? 'storage'\n      : 'read-only-storage';\n};\n\nconst toBindGroupLayoutsResource = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TIncludeUniform extends boolean, TIncludeEntity extends boolean>(\n  name: string,\n  visibility: GPUShaderStageFlags,\n  groupBindings: Array<WPKGroupBinding<TUniform, TEntity, TBufferFormatMap, TIncludeUniform, TIncludeEntity>>,\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>\n): WPKResource<GPUBindGroupLayout[]> => {\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Creating bind group layouts resource');\n  const bindGroupLayoutResources: WPKResource<GPUBindGroupLayout>[] = [];\n  for (let group = 0; group <= shaderReserved.MAX_GROUP_INDEX; group++) {\n    const groupName = `${name}-group-${group}`;\n    const bindGroupLayoutEntries = toBindGroupLayoutEntries(groupBindings, group as WPKGroupIndex, visibility, bufferLayouts);\n    if (bindGroupLayoutEntries.length > 0) {\n      logFuncs.lazyDebug(PIPELINE_LOGGER, () => `${groupName} entries count: ${bindGroupLayoutEntries.length}`);\n      const bindGroupLayoutResource = pipelineResourceFactory.ofBindGroupLayout(groupName, bindGroupLayoutEntries);\n      bindGroupLayoutResources[group] = bindGroupLayoutResource;\n    }\n  }\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Creating array resource of ${bindGroupLayoutResources.length} bind group layout resources`);\n  return resourceFactory.ofArray(bindGroupLayoutResources);\n};\n\nconst toBindGroupsDetailResource = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TIncludeUniform extends boolean, TIncludeEntity extends boolean>(\n  name: string,\n  visibility: GPUShaderStageFlags,\n  groupBindings: Array<WPKGroupBinding<TUniform, TEntity, TBufferFormatMap, TIncludeUniform, TIncludeEntity>>,\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>,\n  bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>,\n  dispatchBuffer?: WPKResource<WPKTrackedBuffer>\n): WPKResource<WPKBindGroupsDetail> => {\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => 'Creating bind groups detail resource');\n  const bindGroupDetailResources: WPKResource<WPKBindGroupDetail>[] = [];\n  for (let group = 0; group <= shaderReserved.MAX_GROUP_INDEX; group++) {\n    const groupName = `${name}-group-${group}`;\n    const bindGroupLayoutEntries = toBindGroupLayoutEntries(groupBindings, group as WPKGroupIndex, visibility, bufferLayouts);\n    if (bindGroupLayoutEntries.length > 0) {\n      logFuncs.lazyDebug(PIPELINE_LOGGER, () => `${groupName} entries count: ${bindGroupLayoutEntries.length}`);\n      const bindGroupLayoutResource = pipelineResourceFactory.ofBindGroupLayout(groupName, bindGroupLayoutEntries);\n      const bindGroupEntriesResources = toBindGroupEntriesResources(groupBindings, group as WPKGroupIndex, bufferResources, dispatchBuffer);\n      const bindGroupEntriesResource = resourceFactory.ofArray(bindGroupEntriesResources);\n      const bindGroupResource = pipelineResourceFactory.ofBindGroup(groupName, bindGroupLayoutResource, bindGroupEntriesResource);\n      const bindGroupDetailResource = pipelineResourceFactory.ofBindGroupDetail(group as WPKGroupIndex, bindGroupResource);\n      bindGroupDetailResources.push(bindGroupDetailResource);\n    }\n  }\n  return resourceFactory.ofArray(bindGroupDetailResources);\n};\n\nconst toBindGroupEntriesResources = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>, TIncludeUniform extends boolean, TIncludeEntity extends boolean>(\n  groupBindings: Array<WPKGroupBinding<TUniform, TEntity, TBufferFormatMap, TIncludeUniform, TIncludeEntity>>,\n  group: WPKGroupIndex,\n  bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>,\n  dispatchBuffer?: WPKResource<WPKTrackedBuffer>\n): WPKResource<GPUBindGroupEntry>[] => {\n  logFuncs.lazyDebug(PIPELINE_LOGGER, () => `Creating bind group entries resources for group ${group}`);\n  return groupBindings.filter(groupBinding => groupBinding.group === group)\n    .map((groupBinding) => {\n      const { binding, buffer } = groupBinding;\n      const bufferResource = (buffer === shaderReserved.DISPATCH_PARAMS_BUFFER_NAME)\n        ? dispatchBuffer\n        : bufferResources.buffers[buffer as WPKBufferFormatKey<TUniform, TEntity, TBufferFormatMap, any, any>];\n      if (bufferResource === undefined) {\n        throw Error(`Failed to find buffer resource for ${buffer}`);\n      }\n      return pipelineResourceFactory.ofBindGroupEntry(binding, bufferResource);\n    });\n};\n\nconst toReadBackFuncResource = <TUniform, TEntity, TBufferFormatMap extends WPKBufferFormatMap<TUniform, TEntity>>(\n  bufferLayouts: WPKBufferLayouts<TUniform, TEntity>,\n  bufferResources: WPKBufferResources<TUniform, TEntity, TBufferFormatMap>,\n  dispatchResource: WPKDispatchResource<any> | undefined,\n  entityCache: WPKEntityCache<TEntity, any, any>,\n  readBackOptions: WPKReadBackOptions<TUniform, TEntity, TBufferFormatMap>,\n): WPKResource<WPKReadBackFuncs> | undefined => {\n  logFuncs.lazyDebug(BUFFER_LOGGER, () => 'Checking for onReadBack func');\n  const { onReadBack } = readBackOptions;\n  if (onReadBack === undefined) {\n    logFuncs.lazyDebug(BUFFER_LOGGER, () => 'onReadBack func not found');\n    return;\n  }\n  logFuncs.lazyInfo(BUFFER_LOGGER, () => 'Creating read back function resource');\n  const sourceTargetBuffers = {} as Record<string, { layout: WPKBufferLayout<any, any>; source: WPKResource<WPKTrackedBuffer>; target: WPKBufferResizeable & WPKResource<WPKTrackedBuffer>; }>;\n  const addSourceTargetBuffers = (bufferName: string, layout: WPKBufferLayout<any, any>, source: WPKResource<WPKTrackedBuffer>): void => {\n    const target = bufferFactory.ofResizeable(false, `${bufferName}-readback`, GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, false);\n    sourceTargetBuffers[bufferName] = {\n      layout,\n      source,\n      target,\n    };\n  };\n  for (const [bufferName, bufferResourceObj] of Object.entries(bufferResources.buffers)) {\n    const layout = bufferLayouts[bufferName];\n    addSourceTargetBuffers(bufferName, layout, bufferResourceObj as WPKResource<WPKTrackedBuffer>);\n  }\n  if (dispatchResource !== undefined) {\n    addSourceTargetBuffers(shaderReserved.DISPATCH_PARAMS_BUFFER_NAME, dispatchResource.layout, dispatchResource.buffer);\n  }\n  let readBackFunc: WPKReadBackFuncs | undefined;\n  return {\n    update(device, queue, encoder) {\n      logFuncs.lazyDebug(BUFFER_LOGGER, () => 'Creating read back function');\n      const readBackBuffers = {} as Record<string, { layout: WPKBufferLayout<any, any>; buffer: WPKTrackedBuffer }>;\n      for (const [bufferName, { layout, source, target }] of Object.entries(sourceTargetBuffers)) {\n        const sourceBuffer = source.get();\n        const copyBytesLength = sourceBuffer.bytesLength;\n        logFuncs.lazyDebug(BUFFER_LOGGER, () => `Resizing read back buffer ${bufferName}`);\n        target.resize(copyBytesLength);\n        logFuncs.lazyDebug(BUFFER_LOGGER, () => `Updating read back buffer ${bufferName}`);\n        target.update(device, queue, encoder);\n        const targetBuffer = target.get();\n        logFuncs.lazyDebug(BUFFER_LOGGER, () => `Copying data ${copyBytesLength} bytes from ${sourceBuffer.buffer.label} to read back buffer ${targetBuffer.buffer.label}`);\n        encoder.copyBufferToBuffer(sourceBuffer.buffer, 0, targetBuffer.buffer, 0, copyBytesLength);\n        readBackBuffers[bufferName] = {\n          layout,\n          buffer: targetBuffer\n        };\n      }\n      const entityCount = entityCache.count();\n      readBackFunc = {\n        copyData(encoder) {\n          logFuncs.lazyDebug(BUFFER_LOGGER, () => 'Copy data from source buffers to read back buffers');\n          for (const { source, target } of Object.values(sourceTargetBuffers)) {\n            const sourceBuffer = source.get();\n            const targetBuffer = target.get();\n            const copyBytesLength = sourceBuffer.bytesLength;\n            logFuncs.lazyTrace(BUFFER_LOGGER, () => `Copying data ${copyBytesLength} bytes from ${sourceBuffer.buffer.label} to read back buffer ${targetBuffer.buffer.label}`);\n            encoder.copyBufferToBuffer(sourceBuffer.buffer, 0, targetBuffer.buffer, 0, copyBytesLength);\n          }\n        },\n        async readBack() {\n          logFuncs.lazyDebug(BUFFER_LOGGER, () => `Read back ${Object.values(readBackBuffers).length} buffers`);\n          const contentMap = {} as WPKReadBackContentMap<TUniform, TEntity, TBufferFormatMap>;\n          logFuncs.lazyTrace(BUFFER_LOGGER, () => 'Convert read back funcs to promises');\n          const promises = Object.entries(readBackBuffers)\n            .map(([bufferName, { buffer, layout }]) => {\n              const instanceCount = (layout.structType === 'uniform')\n                ? 1\n                : entityCount;\n              logFuncs.lazyTrace(BUFFER_LOGGER, () => `Instance count from buffer type ${layout.structType} ${instanceCount}`);\n              return addInstanceContents(\n                bufferName,\n                buffer,\n                layout,\n                instanceCount,\n                contentMap);\n            });\n          await Promise.all(promises);\n          logFuncs.lazyTrace(BUFFER_LOGGER, () => 'Invoke onReadBack(contentMap)');\n          onReadBack(contentMap);\n        },\n      };\n    },\n    get() {\n      return resourceFactory.getOrThrow(readBackFunc, 'read back func');\n    },\n    clean() {\n      Object.values(sourceTargetBuffers).forEach(sourceTargetBuffer => {\n        sourceTargetBuffer.source.clean();\n        sourceTargetBuffer.target.clean();\n      });\n      dispatchResource?.buffer.clean();\n    },\n  };\n};\n\nconst addInstanceContents = async <T>(\n  bufferName: string,\n  buffer: WPKTrackedBuffer,\n  bufferLayout: WPKBufferLayout<T, any>,\n  instanceCount: number,\n  contentMap: WPKReadBackContentMap<any, any, any>\n): Promise<void> => {\n  logFuncs.lazyDebug(BUFFER_LOGGER, () => `Synching ${buffer.buffer.label} read back buffer for read`);\n  await buffer.buffer.mapAsync(GPUMapMode.READ);\n  const mappedRange = buffer.buffer.getMappedRange().slice(0);\n  buffer.buffer.unmap();\n  const dataView = new DataView(mappedRange);\n  logFuncs.lazyDebug(BUFFER_LOGGER, () => `Unmarshalling from ${buffer.buffer.label}`);\n  logFuncs.lazyTrace(BUFFER_LOGGER, () => `Contents for buffer '${buffer.buffer.label}' bytes: [${new Uint8Array(mappedRange)}]`);\n  logFuncs.lazyTrace(BUFFER_LOGGER, () => `Contents for buffer '${buffer.buffer.label}' floats: [${new Float32Array(mappedRange)}]`);\n  const instances = unmarshallToInstances(dataView, bufferLayout, instanceCount);\n  contentMap[bufferName] = (bufferLayout.structType === 'uniform')\n    ? instances[0]\n    : instances;\n};\n\nexport const unmarshallToInstances = <T>(\n  dataView: DataView,\n  bufferLayout: WPKBufferLayout<T, any>,\n  instanceCount: number,\n): Record<string, any>[] => {\n  const { entries } = bufferLayout;\n  const instances: Record<string, any>[] = Array(instanceCount);\n  for (let i = 0; i < instanceCount; i++) {\n    const instance = {};\n    for (const entry of Object.values(entries)) {\n      entry.bridge.dataViewToInstance(0, instance, dataView);\n    }\n    instances[i] = instance;\n  }\n  return instances;\n};\n","import { getLogger } from './logging';\nimport { WPKEventListenerRemover, WPKKeyEventInfo, WPKMouseButton, WPKMouseButtonEventInfo, WPKMouseDragEventInfo, WPKMouseMoveEventInfo, WPKPeripheralEventHandler, WPKPeripheralEventHandlers, WPKPeripheralEventInfoTypeMap, WPKPeripheralEventType, WPKScreenEventInfo, WPKScreenXY } from './types';\nimport { changeDetectorFactory, logFuncs, WPKChangeDetector } from './utils';\n\nconst LOGGER = getLogger('events');\n\ntype WPKCoords = [number, number];\n\nexport const addPeripheralEventHandlers = (\n  canvas: HTMLCanvasElement,\n  handlers: WPKPeripheralEventHandlers,\n  eventsWindow: Window | undefined = window\n): WPKEventListenerRemover => {\n  if (typeof eventsWindow === 'undefined') {\n    return {\n      remove() {\n      }\n    };\n  }\n  const removers: WPKEventListenerRemover[] = [];\n  const screenPosition: WPKCoords = [0, 0];\n  const screenSize: WPKCoords = [0, 0];\n  setupKeyHandlers(handlers, eventsWindow, removers);\n  setupMouseHandlers(handlers, eventsWindow, removers, screenPosition, screenSize);\n  setupScreenHandlers(canvas, handlers, eventsWindow, removers, screenPosition, screenSize);\n  return {\n    remove() {\n      logFuncs.lazyInfo(LOGGER, () => `Removing ${removers.length} event handlers`);\n      removers.forEach((remover) => {\n        try {\n          remover.remove();\n        } catch (error) {\n          logFuncs.lazyWarn(LOGGER, () => `Error when removing listener ${error}`);\n        }\n      });\n      removers.length = 0;\n    },\n  };\n};\n\nconst setupKeyHandlers = (\n  handlers: WPKPeripheralEventHandlers,\n  eventsWindow: Window,\n  eventListenerRemovers: WPKEventListenerRemover[]\n): void => {\n  logFuncs.lazyInfo(LOGGER, () => 'Adding key event handlers');\n  const handlerKeyDown = handlers[WPKPeripheralEventType.KEY_DOWN];\n  const handlerKeyPress = handlers[WPKPeripheralEventType.KEY_PRESS];\n  const handlerKeyUp = handlers[WPKPeripheralEventType.KEY_UP];\n  if (handlerKeyDown !== undefined) {\n    eventListenerRemovers.push(addKeyEventListener(eventsWindow, handlerKeyDown, WPKPeripheralEventType.KEY_DOWN, 'keydown'));\n  }\n  if (handlerKeyPress !== undefined) {\n    eventListenerRemovers.push(addKeyEventListener(eventsWindow, handlerKeyPress, WPKPeripheralEventType.KEY_PRESS, 'keypress'));\n  }\n  if (handlerKeyUp !== undefined) {\n    eventListenerRemovers.push(addKeyEventListener(eventsWindow, handlerKeyUp, WPKPeripheralEventType.KEY_UP, 'keyup'));\n  }\n};\n\nconst setupMouseHandlers = (\n  handlers: WPKPeripheralEventHandlers,\n  eventsWindow: Window,\n  eventListenerRemovers: WPKEventListenerRemover[],\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords,\n): void => {\n  logFuncs.lazyInfo(LOGGER, () => 'Adding mouse event handlers');\n  const handlerMouseDown = handlers[WPKPeripheralEventType.MOUSE_DOWN];\n  const handlerMouseDrag = handlers[WPKPeripheralEventType.MOUSE_DRAG];\n  const handlerMouseUp = handlers[WPKPeripheralEventType.MOUSE_UP];\n  const handlerMouseMove = handlers[WPKPeripheralEventType.MOUSE_MOVE];\n  const isMouseMoveRequired = (handlerMouseDrag !== undefined) || (handlerMouseMove !== undefined);\n  const isMouseDownRequired = isMouseMoveRequired || (handlerMouseDown !== undefined);\n  const isMouseUpRequired = (handlerMouseUp !== undefined);\n  const mousePosition: WPKCoords = [0, 0];\n  const mouseDrag: WPKCoords = [0, 0];\n  const mouseDown: WPKCoords = [-1, -1];\n  const mouseDownButton = changeDetectorFactory.ofTripleEquals<WPKMouseButton>(WPKMouseButton.LEFT);\n  if (isMouseMoveRequired) {\n    logFuncs.lazyInfo(LOGGER, () => 'Adding mouse move listener');\n    eventListenerRemovers.push(addMouseMoveListener(eventsWindow, handlerMouseDrag, handlerMouseMove, screenPosition, screenSize, mousePosition, mouseDrag, mouseDown, mouseDownButton));\n  }\n  if (isMouseDownRequired) {\n    eventListenerRemovers.push(addMouseButtonListener(eventsWindow, handlerMouseDown, WPKPeripheralEventType.MOUSE_DOWN, 'mousedown', screenPosition, screenSize, mousePosition, mouseDown, mouseDownButton));\n  }\n  if (isMouseUpRequired) {\n    eventListenerRemovers.push(addMouseButtonListener(eventsWindow, handlerMouseUp, WPKPeripheralEventType.MOUSE_UP, 'mouseup', screenPosition, screenSize, mousePosition, mouseDown, mouseDownButton));\n  }\n};\n\nconst setupScreenHandlers = (\n  canvas: HTMLCanvasElement,\n  handlers: WPKPeripheralEventHandlers,\n  eventsWindow: Window,\n  eventListenerRemovers: WPKEventListenerRemover[],\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords,\n): void => {\n  logFuncs.lazyInfo(LOGGER, () => 'Adding screen event handlers');\n  const handlerScreenResize = handlers[WPKPeripheralEventType.SCREEN_RESIZE];\n  const isScreenResizeRequired = (handlerScreenResize !== undefined)\n    || (handlers[WPKPeripheralEventType.MOUSE_DOWN] !== undefined)\n    || (handlers[WPKPeripheralEventType.MOUSE_DRAG] !== undefined)\n    || (handlers[WPKPeripheralEventType.MOUSE_MOVE] !== undefined)\n    || (handlers[WPKPeripheralEventType.MOUSE_UP] !== undefined)\n    ;\n  if (isScreenResizeRequired) {\n    updateScreenBounds(eventsWindow, canvas, screenPosition, screenSize);\n    eventListenerRemovers.push(addScreenResizeListener(eventsWindow, handlerScreenResize, canvas, screenPosition, screenSize));\n    if (handlerScreenResize !== undefined) {\n      const eventInfo: WPKScreenEventInfo = {\n        width: screenSize[0],\n        height: screenSize[1],\n        aspectRatio: screenSize[0] / screenSize[1],\n        timestamp: 0,\n      };\n      invokeHandler(handlerScreenResize, WPKPeripheralEventType.SCREEN_RESIZE, eventInfo);\n    }\n  }\n};\n\nconst addKeyEventListener = <TEventType extends WPKPeripheralEventType.KEY_DOWN | WPKPeripheralEventType.KEY_PRESS | WPKPeripheralEventType.KEY_UP>(\n  eventsWindow: Window,\n  handler: WPKPeripheralEventHandler<TEventType>,\n  eventType: TEventType,\n  eventName: 'keydown' | 'keypress' | 'keyup'\n): WPKEventListenerRemover => {\n  const listener = (event: KeyboardEvent) => {\n    logFuncs.lazyTrace(LOGGER, () => `Handling ${eventName} event`);\n    invokeHandler(handler, eventType, toKeyEventInfo(event));\n  };\n  logFuncs.lazyInfo(LOGGER, () => `Adding ${eventName} listener`);\n  eventsWindow.addEventListener(eventName, listener, { passive: true });\n  return {\n    remove() {\n      logFuncs.lazyInfo(LOGGER, () => `Removing ${eventName} listener`);\n      eventsWindow.removeEventListener(eventName, listener);\n    },\n  };\n};\n\nconst addMouseMoveListener = (\n  eventsWindow: Window,\n  mouseDragHandler: WPKPeripheralEventHandler<WPKPeripheralEventType.MOUSE_DRAG> | undefined,\n  mouseMoveHandler: WPKPeripheralEventHandler<WPKPeripheralEventType.MOUSE_MOVE> | undefined,\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords,\n  mousePosition: WPKCoords,\n  mouseDrag: WPKCoords,\n  mouseDown: WPKCoords,\n  mouseDownButton: WPKChangeDetector<WPKMouseButton>\n): WPKEventListenerRemover => {\n  const listener = (event: MouseEvent) => {\n    logFuncs.lazyTrace(LOGGER, () => `Handling ${event.type} event`);\n    updateMousePositions(event, screenPosition, mousePosition);\n    if (event.buttons > 0) {\n      //mouse drag\n      if (mouseDragHandler !== undefined) {\n        if (mouseDown[0] === -1 || mouseDown[1] === -1) {\n          logFuncs.lazyTrace(LOGGER, () => 'Waiting for mouse down event before sending drag events');\n        } else {\n          mouseDrag[0] = mousePosition[0] - mouseDown[0];\n          mouseDrag[1] = mousePosition[1] - mouseDown[1];\n          const eventInfo = toMouseDragEventInfo(event, screenSize, mousePosition, mouseDrag, mouseDownButton);\n          invokeHandler(mouseDragHandler, WPKPeripheralEventType.MOUSE_DRAG, eventInfo);\n        }\n      }\n    } else {\n      // mouse move\n      if (mouseMoveHandler !== undefined) {\n        const eventInfo = toMouseMoveEventInfo(event, screenSize, mousePosition);\n        invokeHandler(mouseMoveHandler, WPKPeripheralEventType.MOUSE_MOVE, eventInfo);\n      }\n    }\n  };\n  logFuncs.lazyInfo(LOGGER, () => 'Adding mousemove listener');\n  eventsWindow.addEventListener('mousemove', listener, { passive: true });\n  return {\n    remove() {\n      logFuncs.lazyInfo(LOGGER, () => 'Removing mousemove listener');\n      eventsWindow.removeEventListener('mousemove', listener);\n    },\n  };\n};\n\nconst buttonMap: Record<number, WPKMouseButton> = {\n  0: WPKMouseButton.LEFT,\n  1: WPKMouseButton.MIDDLE,\n  2: WPKMouseButton.RIGHT,\n  3: WPKMouseButton.BACK,\n  4: WPKMouseButton.FORWARD,\n};\n\nconst addMouseButtonListener = <TEventType extends WPKPeripheralEventType.MOUSE_DOWN | WPKPeripheralEventType.MOUSE_UP>(\n  eventsWindow: Window,\n  handler: WPKPeripheralEventHandler<TEventType> | undefined,\n  eventType: TEventType,\n  eventName: 'mousedown' | 'mouseup',\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords,\n  mousePosition: WPKCoords,\n  mouseDown: WPKCoords,\n  mouseDownButton: WPKChangeDetector<WPKMouseButton>\n): WPKEventListenerRemover => {\n  const listener = createRAFThrottledHandler((event: MouseEvent) => {\n    logFuncs.lazyTrace(LOGGER, () => `Handling ${event.type} event`);\n    const { button } = event;\n    if (eventName === 'mousedown') {\n      const mouseButton = buttonMap[button];\n      if (mouseButton !== undefined) {\n        mouseDownButton.compareAndUpdate(mouseButton);\n      } else {\n        logFuncs.lazyWarn(LOGGER, () => `Mouse button ${button} will not trigger events`);\n      }\n    }\n    updateMousePositions(event, screenPosition, mousePosition);\n    if (eventName === 'mousedown') {\n      mouseDown[0] = mousePosition[0];\n      mouseDown[1] = mousePosition[1];\n    } else {\n      mouseDown[0] = -1;\n      mouseDown[1] = -1;\n    }\n    if (handler !== undefined) {\n      const eventInfo = toMouseButtonEventInfo(event, screenSize, mousePosition, mouseDownButton);\n      invokeHandler(handler, eventType, eventInfo);\n    }\n  });\n  logFuncs.lazyInfo(LOGGER, () => `Adding ${eventName} event listener`);\n  eventsWindow.addEventListener(eventName, listener, { passive: true });\n  return {\n    remove() {\n      logFuncs.lazyInfo(LOGGER, () => `Removing ${eventName} event listener`);\n      eventsWindow.removeEventListener(eventName, listener);\n    },\n  };\n};\n\nconst addScreenResizeListener = (\n  eventsWindow: Window,\n  handler: WPKPeripheralEventHandler<WPKPeripheralEventType.SCREEN_RESIZE> | undefined,\n  canvas: HTMLCanvasElement,\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords\n): WPKEventListenerRemover => {\n  const listener = createRAFThrottledHandler((event: UIEvent) => {\n    logFuncs.lazyInfo(LOGGER, () => `Handling ${event.type} event`);\n    updateScreenBounds(eventsWindow, canvas, screenPosition, screenSize);\n    if (handler !== undefined) {\n      const eventInfo = {\n        width: screenSize[0],\n        height: screenSize[1],\n        aspectRatio: screenSize[0] / screenSize[1],\n        timestamp: event.timeStamp,\n      };\n      invokeHandler(handler, WPKPeripheralEventType.SCREEN_RESIZE, eventInfo);\n    }\n  });\n  logFuncs.lazyInfo(LOGGER, () => 'Adding resize event listener');\n  eventsWindow.addEventListener('resize', listener, { passive: true });\n  return {\n    remove() {\n      logFuncs.lazyInfo(LOGGER, () => 'Removing resize event listener');\n      eventsWindow.removeEventListener('resize', listener);\n    },\n  };\n};\n\nconst updateScreenBounds = (\n  eventsWindow: Window,\n  canvas: HTMLCanvasElement,\n  screenPosition: WPKCoords,\n  screenSize: WPKCoords\n): void => {\n  const { left, top, width, height } = canvas.getBoundingClientRect();\n  screenPosition[0] = left;\n  screenPosition[1] = top;\n  screenSize[0] = width;\n  screenSize[1] = height;\n  const pixelRatio = eventsWindow.devicePixelRatio || 1;\n  const desiredWidth = Math.floor(width * pixelRatio);\n  const desiredHeight = Math.floor(height * pixelRatio);\n  if (canvas.width !== desiredWidth) {\n    canvas.width = desiredWidth;\n  }\n  if (canvas.height !== desiredHeight) {\n    canvas.height = desiredHeight;\n  }\n  logFuncs.lazyTrace(LOGGER, () => `Updated screen position ${screenPosition} and size ${screenSize}`);\n};\n\nconst updateMousePositions = (\n  event: MouseEvent,\n  screenPosition: WPKCoords,\n  mousePosition: WPKCoords,\n): void => {\n  const { clientX, clientY } = event;\n  mousePosition[0] = clientX - screenPosition[0];\n  mousePosition[1] = clientY - screenPosition[1];\n};\n\nconst toKeyEventInfo = (event: KeyboardEvent): WPKKeyEventInfo => ({\n  code: event.code,\n  key: event.key,\n  modifiers: {\n    alt: event.altKey,\n    ctrl: event.ctrlKey,\n    meta: event.metaKey,\n    shift: event.shiftKey,\n  },\n  isRepeat: event.repeat,\n  timestamp: event.timeStamp,\n});\n\nconst toMouseButtonEventInfo = (event: MouseEvent, screenSize: WPKCoords, mousePosition: WPKCoords, mouseDownButton: WPKChangeDetector<WPKMouseButton>): WPKMouseButtonEventInfo => ({\n  position: toScreenXY(screenSize, mousePosition),\n  trigger: mouseDownButton.get(),\n  pressed: toMouseButtons(event),\n  repeatCount: event.detail,\n  timestamp: event.timeStamp,\n});\n\nconst toMouseMoveEventInfo = (event: MouseEvent, screenSize: WPKCoords, mousePosition: WPKCoords): WPKMouseMoveEventInfo => ({\n  position: toScreenXY(screenSize, mousePosition),\n  timestamp: event.timeStamp,\n});\n\nconst toMouseDragEventInfo = (event: MouseEvent, screenSize: WPKCoords, mousePosition: WPKCoords, mouseDrag: WPKCoords, mouseDownButton: WPKChangeDetector<WPKMouseButton>): WPKMouseDragEventInfo => ({\n  position: toScreenXY(screenSize, mousePosition),\n  drag: toScreenXY(screenSize, mouseDrag),\n  trigger: mouseDownButton.get(),\n  pressed: toMouseButtons(event),\n  repeatCount: event.detail,\n  timestamp: event.timeStamp,\n});\n\nconst toMouseButtons = (event: MouseEvent): WPKMouseButton[] => {\n  const { buttons } = event;\n  const buttonsPressed: WPKMouseButton[] = [];\n  if (buttons & 1) {\n    buttonsPressed.push(WPKMouseButton.LEFT);\n  }\n  if (buttons & 2) {\n    buttonsPressed.push(WPKMouseButton.RIGHT);\n  }\n  if (buttons & 4) {\n    buttonsPressed.push(WPKMouseButton.MIDDLE);\n  }\n  if (buttons & 8) {\n    buttonsPressed.push(WPKMouseButton.BACK);\n  }\n  if (buttons & 16) {\n    buttonsPressed.push(WPKMouseButton.FORWARD);\n  }\n  return buttonsPressed;\n};\n\nconst toScreenXY = (screenSize: WPKCoords, mousePosition: WPKCoords): WPKScreenXY => {\n  const x = mousePosition[0];\n  const y = mousePosition[1];\n  return {\n    absolute: {\n      x,\n      y,\n    },\n    normalized: {\n      x: x / screenSize[0],\n      y: y / screenSize[1],\n    },\n  };\n};\n\nconst invokeHandler = <TEventType extends keyof WPKPeripheralEventHandlers>(\n  handler: WPKPeripheralEventHandler<TEventType>,\n  eventType: TEventType,\n  eventInfo: WPKPeripheralEventInfoTypeMap[TEventType]\n): void => {\n  try {\n    handler(eventInfo);\n  } catch (error) {\n    logFuncs.lazyError(LOGGER, () => `Error in ${eventType} handler. ${error}`);\n  }\n};\n\nconst createRAFThrottledHandler = <T extends (...args: any[]) => void>(fn: T): T => {\n  let ticking = false;\n  let latestArgs: any[] = [];\n  return ((...args: any[]) => {\n    latestArgs = args;\n    if (!ticking) {\n      ticking = true;\n      requestAnimationFrame(() => {\n        fn(...latestArgs);\n        ticking = false;\n      });\n    }\n  }) as T;\n};\n","import { getLogger } from './logging';\nimport { addPeripheralEventHandlers } from './peripheral-events';\nimport { pipelineFuncs } from './pipeline-utils';\nimport { WPKAddPipelineOptions, WPKAddPipelineOptionsAddAfter, WPKAddPipelineOptionsAddBefore, WPKComputePipelineDetail, WPKEventListenerRemover, WPKPipeline, WPKPipelineDetail, WPKPipelineInvoker, WPKPipelineRunner, WPKRenderPipelineDetail, WPKPipelineRenderOptions, WPKViews, WPKViewsFunc } from './types';\nimport { logFuncs } from './utils';\n\nconst LOGGER = getLogger('pipeline');\n\nconst isOptionsAddBefore = (options?: WPKAddPipelineOptions): options is WPKAddPipelineOptionsAddBefore => (options !== undefined && (options as WPKAddPipelineOptionsAddBefore).before !== undefined);\nconst isOptionsAddAfter = (options?: WPKAddPipelineOptions): options is WPKAddPipelineOptionsAddAfter => (options !== undefined && (options as WPKAddPipelineOptionsAddAfter).after !== undefined);\n\nexport const pipelineRunnerFactory = {\n  create: async (renderOptions?: WPKPipelineRenderOptions): Promise<WPKPipelineRunner> => {\n    logFuncs.lazyInfo(LOGGER, () => 'Creating pipeline runner');\n    const gpu = pipelineFuncs.getGpu();\n    const device = await pipelineFuncs.getDevice(gpu);\n    let getViews: WPKViewsFunc;\n    let clearValue: number[];\n    let remover: WPKEventListenerRemover;\n    if (renderOptions === undefined) {\n      getViews = (() => ({})) as WPKViewsFunc;\n      clearValue = [];\n      remover = { remove() { }, };\n    } else {\n      getViews = await createViewsGetter(renderOptions.canvas, device);\n      clearValue = [renderOptions.clearColor.r, renderOptions.clearColor.g, renderOptions.clearColor.b, renderOptions.clearColor.a];\n      remover = addPeripheralEventHandlers(renderOptions.canvas, renderOptions.peripheralEventHandlers);\n    }\n    const invoker: WPKPipelineInvoker = (encoder, index, detail) => {\n      logFuncs.lazyTrace(LOGGER, () => `Invoking pipeline ${JSON.stringify(detail)}`);\n      const { compute, render } = detail;\n      if (compute !== undefined) {\n        invokeComputePipeline(compute, index, encoder);\n      }\n      if (render !== undefined) {\n        if (renderOptions === undefined) {\n          logFuncs.lazyWarn(LOGGER, () => `Cannot invoke render pipeline for ${detail.name}, set render options parameter when creating pipeline runner`);\n        } else {\n          const views = getViews();\n          invokeRenderPipeline(render, index, encoder, views, clearValue);\n        }\n      }\n    };\n    return createPipelineRunner(device, invoker, remover);\n  },\n};\n\nconst createViewsGetter = async (canvas: HTMLCanvasElement, device: GPUDevice): Promise<WPKViewsFunc> => {\n  const context = pipelineFuncs.getContext(canvas);\n  const gpu = pipelineFuncs.getGpu();\n  const format = pipelineFuncs.getFormat(gpu);\n  const alphaMode = 'opaque';\n  context.configure({\n    alphaMode,\n    device,\n    format,\n  });\n  return createViewsFunc(canvas, context, device, format);\n};\n\nconst createPipelineRunner = async (\n  device: GPUDevice,\n  pipelineInvoker: (encoder: GPUCommandEncoder, index: number, detail: WPKPipelineDetail) => void,\n  remover?: WPKEventListenerRemover\n): Promise<WPKPipelineRunner> => {\n  logFuncs.lazyInfo(LOGGER, () => 'Creating pipeline runner');\n  const pipelines: WPKPipeline<any, any, any, any, any>[] = [];\n  return {\n    add(pipeline, options) {\n      const { name } = pipeline;\n      if (pipelines.findIndex((pipeline) => pipeline.name === name) !== -1) {\n        throw Error(`Cannot add a pipeline with duplicate name '${name}'`);\n      }\n      const insertIndex = toInsertIndex(pipelines, options);\n      logFuncs.lazyInfo(LOGGER, () => `Adding pipeline '${name}'`);\n      pipelines.splice(insertIndex, 0, pipeline);\n    },\n    remove(name) {\n      const removeIndex = toInsertIndexFromName(pipelines, name, false);\n      if (removeIndex === -1) {\n        logFuncs.lazyWarn(LOGGER, () => `No pipeline to remove with name '${name}'`);\n      } else {\n        logFuncs.lazyInfo(LOGGER, () => `Removing pipeline '${name}'`);\n        pipelines.splice(removeIndex, 1);\n      }\n    },\n    async step() {\n      const encoder = device.createCommandEncoder({\n        label: 'command-encoder',\n      });\n      const { queue } = device;\n      logFuncs.lazyTrace(LOGGER, () => `Creating pipeline details from ${pipelines.length} pipelines`);\n      const pipelineDetails = pipelines.map((pipeline) => pipeline.pipelineDetail(device, queue, encoder));\n      const invalidPipelineNames = pipelineDetails\n        .filter((pipelineDetail) => pipelineDetail.instanceCount === 0)\n        .map(pipelineDetail => pipelineDetail.name);\n      if (invalidPipelineNames.length > 0) {\n        logFuncs.lazyInfo(LOGGER, () => `No entities for pipelines [${invalidPipelineNames.join(', ')}]`);\n      }\n      const validPipelines = pipelineDetails.filter((pipelineDetail) => pipelineDetail.instanceCount > 0);\n      logFuncs.lazyDebug(LOGGER, () => `Invoking ${validPipelines.length} valid pipelines`);\n      for (const [pipelineIndex, pipelineDetail] of validPipelines.entries()) {\n        pipelineInvoker(encoder, pipelineIndex, pipelineDetail);\n      }\n      logFuncs.lazyTrace(LOGGER, () => `Call read back function ${validPipelines.length} pipelines`);\n      const pipelineReadBackFuncs = validPipelines\n        .map(pipeline => pipeline.readBackFuncs)\n        .filter(readBackFuncs => readBackFuncs !== undefined);\n      for (const readBackFuncs of pipelineReadBackFuncs) {\n        readBackFuncs.copyData(encoder);\n      }\n      logFuncs.lazyTrace(LOGGER, () => 'Submit encoder commands');\n      device.queue.submit([encoder.finish()]);\n      const readBackPromises = pipelineReadBackFuncs.map(readBackFuncs => readBackFuncs.readBack());\n      await Promise.all(readBackPromises);\n      logFuncs.lazyTrace(LOGGER, () => `Clean ${pipelines.length} pipelines`);\n      pipelines.forEach(pipeline => pipeline.clean());\n    },\n    destroy() {\n      device.destroy();\n      if (remover !== undefined) {\n        remover.remove();\n      }\n    },\n  };\n};\n\nconst invokeComputePipeline = (compute: WPKComputePipelineDetail[], pipelineIndex: number, encoder: GPUCommandEncoder): void => {\n  logFuncs.lazyTrace(LOGGER, () => `Compute shader of pipeline[${pipelineIndex}]`);\n  const computePass = encoder.beginComputePass();\n  for (const [computeEntryIndex, computeEntry] of compute.entries()) {\n    logFuncs.lazyTrace(LOGGER, () => `Compute pipeline[${pipelineIndex}] entry[${computeEntryIndex}]`);\n    const { bindGroups, pipeline, dispatchCount } = computeEntry;\n    computePass.setPipeline(pipeline);\n    for (const bindGroup of bindGroups) {\n      logFuncs.lazyTrace(LOGGER, () => `Compute pipeline[${pipelineIndex}] entry[${computeEntryIndex}] set bind group at index ${bindGroup.index} to ${bindGroup.group.label}`);\n      computePass.setBindGroup(bindGroup.index, bindGroup.group);\n    }\n    logFuncs.lazyTrace(LOGGER, () => `Compute pipeline[${pipelineIndex}] entry[${computeEntryIndex}] dispatch size ${JSON.stringify(dispatchCount)}`);\n    computePass.dispatchWorkgroups(dispatchCount[0], dispatchCount[1], dispatchCount[2]);\n  }\n  logFuncs.lazyTrace(LOGGER, () => `End compute pass of pipeline[${pipelineIndex}]`);\n  computePass.end();\n};\n\nconst invokeRenderPipeline = (render: WPKRenderPipelineDetail[], pipelineIndex: number, encoder: GPUCommandEncoder, views: WPKViews, clearValue: number[]): void => {\n  logFuncs.lazyTrace(LOGGER, () => `Render shader of pipeline[${pipelineIndex}]`);\n  const renderPass = encoder.beginRenderPass({\n    label: 'render-encoder',\n    colorAttachments: [{\n      ...views,\n      clearValue,\n      loadOp: 'clear',\n      storeOp: 'store'\n    }]\n  });\n  for (const [renderEntryIndex, renderEntry] of render.entries()) {\n    logFuncs.lazyTrace(LOGGER, () => `Render pipeline[${pipelineIndex}] entry[${renderEntryIndex}]`);\n    const { bindGroups, pipeline, indices, vertexBuffers, drawCountsFunc } = renderEntry;\n    const drawCounts = drawCountsFunc();\n    renderPass.setPipeline(pipeline);\n    for (const bindGroup of bindGroups) {\n      logFuncs.lazyTrace(LOGGER, () => `Render pipeline[${pipelineIndex}] entry[${renderEntryIndex}] set bind group at index ${bindGroup.index} to ${bindGroup.group.label}`);\n      renderPass.setBindGroup(bindGroup.index, bindGroup.group);\n    }\n    logFuncs.lazyTrace(LOGGER, () => `Render pipeline[${pipelineIndex}] entry[${renderEntryIndex}] set indices buffer`);\n    renderPass.setIndexBuffer(indices.buffer, indices.format);\n    logFuncs.lazyTrace(LOGGER, () => `Setting ${vertexBuffers.length} vertex buffers`);\n    for (const [slot, vertexBuffer] of vertexBuffers.entries()) {\n      logFuncs.lazyTrace(LOGGER, () => `Render pipeline[${pipelineIndex}] entry[${renderEntryIndex}] set vertex buffer in slot ${slot} ${vertexBuffer.label}`);\n      renderPass.setVertexBuffer(slot, vertexBuffer);\n    }\n    logFuncs.lazyTrace(LOGGER, () => `Render pipeline[${pipelineIndex}] entry[${renderEntryIndex}] draw indexed ${JSON.stringify(drawCounts)}`);\n    renderPass.drawIndexed(drawCounts.indexCount, drawCounts.instanceCount);\n  }\n  logFuncs.lazyTrace(LOGGER, () => `End render pass of pipeline[${pipelineIndex}]`);\n  renderPass.end();\n};\n\nconst createViewsFunc = (canvas: HTMLCanvasElement, context: GPUCanvasContext, device: GPUDevice, format: GPUTextureFormat): WPKViewsFunc => {\n  let viewTexture: GPUTexture | undefined;\n  return (): WPKViews => {\n    const contextView = context.getCurrentTexture().createView();\n    viewTexture = getOrCreateTexture(canvas, device, format, viewTexture);\n    const resolveTarget = contextView;\n    const view = viewTexture.createView();\n    return {\n      resolveTarget,\n      view,\n    };\n  };\n};\n\nconst getOrCreateTexture = (\n  canvas: HTMLCanvasElement,\n  device: GPUDevice,\n  format: GPUTextureFormat,\n  previousAntiAliasingTexture: GPUTexture | undefined,\n): GPUTexture => {\n  const { width, height } = canvas;\n  if (previousAntiAliasingTexture !== undefined) {\n    if (previousAntiAliasingTexture.width === width && previousAntiAliasingTexture.height === height) {\n      return previousAntiAliasingTexture;\n    }\n    previousAntiAliasingTexture.destroy();\n    previousAntiAliasingTexture = undefined;\n  }\n  const sampleCount = pipelineFuncs.ANTI_ALIASED_SAMPLE_COUNT;\n  const size = [width, height];\n  const usage = GPUTextureUsage.RENDER_ATTACHMENT;\n  const descriptor: GPUTextureDescriptor = {\n    format,\n    sampleCount,\n    size,\n    usage,\n  };\n  return device.createTexture(descriptor);\n};\n\nconst toInsertIndex = (pipelines: WPKPipeline<any, any, any, any, any>[], options?: WPKAddPipelineOptions): number => {\n  if (isOptionsAddBefore(options)) {\n    return toInsertIndexFromName(pipelines, options.before, false);\n  } else if (isOptionsAddAfter(options)) {\n    return toInsertIndexFromName(pipelines, options.after, true);\n  } else {\n    return pipelines.length;\n  }\n};\n\nconst toInsertIndexFromName = (pipelines: WPKPipeline<any, any, any, any, any>[], name: string, incrementFoundIndex: boolean): number => {\n  const index = toIndexFromName(pipelines, name);\n  return (index === -1)\n    ? pipelines.length\n    : index + (incrementFoundIndex ? 1 : 0);\n};\n\nconst toIndexFromName = (pipelines: WPKPipeline<any, any, any, any, any>[], name: string): number => pipelines.findIndex((pipeline) => pipeline.name === name);\n","import { meshFactory, meshTemplateFactory } from './mesh-factories';\nimport { pipelineFactory } from './pipeline';\nimport { pipelineRunnerFactory } from './pipeline-runner';\n\nexport const factories = {\n  mesh: meshFactory,\n  meshTemplate: meshTemplateFactory,\n  pipeline: pipelineFactory,\n  pipelineRunner: pipelineRunnerFactory,\n};\n"]}