typegpu 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"deepEqual-yZXvaV2C.js","names":[],"sources":["../src/data/sampler.ts","../src/data/alignIO.ts","../src/data/offsets.ts","../src/data/atomic.ts","../src/data/isContiguous.ts","../src/data/getLongestContiguousPrefix.ts","../src/data/offsetUtils.ts","../src/data/disarray.ts","../src/data/unstruct.ts","../src/data/deepEqual.ts"],"sourcesContent":["import { $internal, $repr } from '../shared/symbols.ts';\nimport type { BaseData } from './wgslTypes.ts';\n\nexport interface WgslSamplerProps {\n addressModeU?: GPUAddressMode;\n addressModeV?: GPUAddressMode;\n /**\n * Specifies the address modes for the texture width, height, and depth\n * coordinates, respectively.\n */\n addressModeW?: GPUAddressMode;\n /**\n * Specifies the sampling behavior when the sample footprint is smaller than or equal to one\n * texel.\n */\n magFilter?: GPUFilterMode;\n /**\n * Specifies the sampling behavior when the sample footprint is larger than one texel.\n */\n minFilter?: GPUFilterMode;\n /**\n * Specifies behavior for sampling between mipmap levels.\n */\n mipmapFilter?: GPUMipmapFilterMode;\n lodMinClamp?: number;\n /**\n * Specifies the minimum and maximum levels of detail, respectively, used internally when\n * sampling a texture.\n */\n lodMaxClamp?: number;\n /**\n * Specifies the maximum anisotropy value clamp used by the sampler. Anisotropic filtering is\n * enabled when {@link GPUSamplerDescriptor.maxAnisotropy} is > 1 and the implementation supports it.\n * Anisotropic filtering improves the image quality of textures sampled at oblique viewing\n * angles. Higher {@link GPUSamplerDescriptor.maxAnisotropy} values indicate the maximum ratio of\n * anisotropy supported when filtering.\n *\n * Most implementations support {@link GPUSamplerDescriptor.maxAnisotropy} values in range\n * between 1 and 16, inclusive. The used value of {@link GPUSamplerDescriptor.maxAnisotropy}\n * will be clamped to the maximum value that the platform supports.\n * The precise filtering behavior is implementation-dependent.\n */\n maxAnisotropy?: number;\n}\n\nexport interface WgslComparisonSamplerProps {\n compare: GPUCompareFunction;\n addressModeU?: GPUAddressMode;\n addressModeV?: GPUAddressMode;\n /**\n * Specifies the address modes for the texture width, height, and depth\n * coordinates, respectively.\n */\n addressModeW?: GPUAddressMode;\n /**\n * Specifies the sampling behavior when the sample footprint is smaller than or equal to one\n * texel.\n */\n magFilter?: GPUFilterMode;\n /**\n * Specifies the sampling behavior when the sample footprint is larger than one texel.\n */\n minFilter?: GPUFilterMode;\n /**\n * Specifies behavior for sampling between mipmap levels.\n */\n mipmapFilter?: GPUMipmapFilterMode;\n lodMinClamp?: number;\n /**\n * Specifies the minimum and maximum levels of detail, respectively, used internally when\n * sampling a texture.\n */\n lodMaxClamp?: number;\n /**\n * Specifies the maximum anisotropy value clamp used by the sampler. Anisotropic filtering is\n * enabled when {@link GPUSamplerDescriptor.maxAnisotropy} is > 1 and the implementation supports it.\n * Anisotropic filtering improves the image quality of textures sampled at oblique viewing\n * angles. Higher {@link GPUSamplerDescriptor.maxAnisotropy} values indicate the maximum ratio of\n * anisotropy supported when filtering.\n *\n * Most implementations support {@link GPUSamplerDescriptor.maxAnisotropy} values in range\n * between 1 and 16, inclusive. The used value of {@link GPUSamplerDescriptor.maxAnisotropy}\n * will be clamped to the maximum value that the platform supports.\n * The precise filtering behavior is implementation-dependent.\n */\n maxAnisotropy?: number;\n}\n\nexport interface sampler {\n [$internal]: true;\n type: 'sampler';\n}\n\nexport function sampler(): WgslSampler {\n return {\n [$internal]: {},\n type: 'sampler',\n [$repr]: undefined as unknown as sampler,\n };\n}\n\nexport interface comparisonSampler {\n [$internal]: Record<string, never>;\n type: 'sampler_comparison';\n}\n\nexport function comparisonSampler(): WgslComparisonSampler {\n return {\n [$internal]: {},\n type: 'sampler_comparison',\n [$repr]: undefined as unknown as comparisonSampler,\n };\n}\n\nexport interface WgslSampler extends BaseData {\n readonly [$repr]: sampler;\n readonly type: 'sampler';\n}\n\nexport interface WgslComparisonSampler extends BaseData {\n readonly [$repr]: comparisonSampler;\n readonly type: 'sampler_comparison';\n}\n\nexport function isWgslSampler(value: unknown): value is WgslSampler {\n return (\n !!(value as WgslSampler)[$internal] &&\n (value as WgslSampler).type === 'sampler'\n );\n}\n\nexport function isWgslComparisonSampler(\n value: unknown,\n): value is WgslComparisonSampler {\n return (\n !!(value as WgslComparisonSampler)[$internal] &&\n (value as WgslComparisonSampler).type === 'sampler_comparison'\n );\n}\n","import type { IMeasurer, ISerialInput, ISerialOutput } from 'typed-binary';\n\n/**\n * @param io the IO to align\n * @param baseAlignment must be power of 2\n */\nfunction alignIO(\n io: ISerialInput | ISerialOutput | IMeasurer,\n baseAlignment: number,\n) {\n const currentPos = 'size' in io ? io.size : io.currentByteOffset;\n\n const bitMask = baseAlignment - 1;\n const offset = currentPos & bitMask;\n\n if ('skipBytes' in io) {\n io.skipBytes((baseAlignment - offset) & bitMask);\n } else {\n io.add((baseAlignment - offset) & bitMask);\n }\n}\n\nexport default alignIO;\n","import { Measurer } from 'typed-binary';\nimport { roundUp } from '../mathUtils.ts';\nimport alignIO from './alignIO.ts';\nimport { alignmentOf, customAlignmentOf } from './alignmentOf.ts';\nimport { isUnstruct, type Unstruct } from './dataTypes.ts';\nimport { sizeOf } from './sizeOf.ts';\nimport type { WgslStruct } from './wgslTypes.ts';\n\nexport interface OffsetInfo {\n offset: number;\n size: number;\n padding?: number | undefined;\n}\n\nconst cachedOffsets = new WeakMap<\n WgslStruct | Unstruct,\n Record<string, OffsetInfo>\n>();\n\nexport function offsetsForProps<T extends WgslStruct | Unstruct>(\n struct: T,\n): Record<keyof T['propTypes'], OffsetInfo> {\n type Key = keyof T['propTypes'];\n\n const cached = cachedOffsets.get(struct);\n if (cached) {\n return cached as Record<Key, OffsetInfo>;\n }\n\n const measurer = new Measurer();\n const offsets = {} as Record<Key, OffsetInfo>;\n let lastEntry: OffsetInfo | undefined;\n\n for (const key in struct.propTypes) {\n const prop = struct.propTypes[key];\n if (prop === undefined) {\n throw new Error(`Property ${key} is undefined in struct`);\n }\n\n const beforeAlignment = measurer.size;\n\n alignIO(\n measurer,\n isUnstruct(struct) ? customAlignmentOf(prop) : alignmentOf(prop),\n );\n\n if (lastEntry) {\n lastEntry.padding = measurer.size - beforeAlignment;\n }\n\n const propSize = sizeOf(prop);\n offsets[key as Key] = { offset: measurer.size, size: propSize };\n lastEntry = offsets[key];\n measurer.add(propSize);\n }\n\n if (lastEntry) {\n lastEntry.padding = roundUp(sizeOf(struct), alignmentOf(struct)) -\n measurer.size;\n }\n\n cachedOffsets.set(struct, offsets);\n return offsets;\n}\n","import type { Infer, MemIdentity } from '../shared/repr.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport {\n $gpuRepr,\n $memIdent,\n $repr,\n $validStorageSchema,\n $validUniformSchema,\n $validVertexSchema,\n} from '../shared/symbols.ts';\nimport type { Atomic, atomicI32, atomicU32, I32, U32 } from './wgslTypes.ts';\n\n// ----------\n// Public API\n// ----------\n\n/**\n * Marks a concrete integer scalar type schema (u32 or i32) as a WGSL atomic.\n *\n * @example\n * const atomicU32 = d.atomic(d.u32);\n * const atomicI32 = d.atomic(d.i32);\n *\n * @param data Underlying type schema.\n */\nexport function atomic<TSchema extends U32 | I32>(\n data: TSchema,\n): Atomic<TSchema> {\n return new AtomicImpl(data);\n}\n\n// --------------\n// Implementation\n// --------------\n\nclass AtomicImpl<TSchema extends U32 | I32> implements Atomic<TSchema> {\n public readonly [$internal] = {};\n public readonly type = 'atomic';\n\n // Type-tokens, not available at runtime\n declare readonly [$repr]: Infer<TSchema>;\n declare readonly [$memIdent]: MemIdentity<TSchema>;\n declare readonly [$gpuRepr]: TSchema extends U32 ? atomicU32 : atomicI32;\n declare readonly [$validStorageSchema]: true;\n declare readonly [$validUniformSchema]: true;\n declare readonly [$validVertexSchema]: true;\n // ---\n\n constructor(public readonly inner: TSchema) {}\n}\n","import type { AnyData } from './dataTypes.ts';\nimport type { BaseData } from './wgslTypes.ts';\nimport { getLayoutInfo } from './schemaMemoryLayout.ts';\n\nexport function isContiguous(schema: BaseData): boolean {\n return getLayoutInfo(schema, 'isContiguous');\n}\n\n/**\n * Returns `true` if data represented by the `schema` doesn't have padding.\n */\nexport function PUBLIC_isContiguous(schema: AnyData): boolean {\n return isContiguous(schema);\n}\n","import type { AnyData } from './dataTypes.ts';\nimport type { BaseData } from './wgslTypes.ts';\nimport { getLayoutInfo } from './schemaMemoryLayout.ts';\n\nexport function getLongestContiguousPrefix(schema: BaseData): number {\n return getLayoutInfo(schema, 'longestContiguousPrefix');\n}\n\n/**\n * Returns the size (in bytes) of the longest contiguous memory prefix of data represented by the `schema`.\n */\nexport function PUBLIC_getLongestContiguousPrefix(schema: AnyData): number {\n return getLongestContiguousPrefix(schema);\n}\n","import { roundUp } from '../mathUtils.ts';\nimport { alignmentOf } from './alignmentOf.ts';\nimport {\n type OffsetInfo as PropOffsetInfo,\n offsetsForProps,\n} from './offsets.ts';\nimport { sizeOf } from './sizeOf.ts';\nimport { isContiguous } from './isContiguous.ts';\nimport { getLongestContiguousPrefix } from './getLongestContiguousPrefix.ts';\nimport type {\n AnyWgslData,\n BaseData,\n VecData,\n WgslArray,\n WgslStruct,\n} from './wgslTypes.ts';\nimport { isVec, isWgslArray, isWgslStruct } from './wgslTypes.ts';\nimport { undecorate } from './dataTypes.ts';\nimport type { Infer } from '../shared/repr.ts';\n\nconst OFFSET_MARKER = Symbol('indirectOffset');\nconst CONTIGUOUS_MARKER = Symbol('indirectContiguous');\n\ninterface OffsetProxy {\n [OFFSET_MARKER]: number;\n [CONTIGUOUS_MARKER]: number;\n}\n\nfunction isOffsetProxy(value: unknown): value is OffsetProxy {\n return (\n typeof value === 'object' &&\n value !== null &&\n OFFSET_MARKER in value &&\n CONTIGUOUS_MARKER in value\n );\n}\n\nfunction scalarNode(offset: number, contiguous: number): OffsetProxy {\n return { [OFFSET_MARKER]: offset, [CONTIGUOUS_MARKER]: contiguous };\n}\n\nfunction getMarker(target: OffsetProxy, prop: PropertyKey): number | undefined {\n if (prop === OFFSET_MARKER) {\n return target[OFFSET_MARKER];\n }\n if (prop === CONTIGUOUS_MARKER) {\n return target[CONTIGUOUS_MARKER];\n }\n return undefined;\n}\n\nfunction makeProxy(\n schema: AnyWgslData,\n baseOffset: number,\n contiguous = sizeOf(schema),\n): unknown {\n const unwrapped = undecorate(schema);\n\n const vecComponentCount = isVec(unwrapped)\n ? unwrapped.componentCount\n : undefined;\n\n if (vecComponentCount !== undefined) {\n const componentSize = sizeOf((unwrapped as VecData).primitive);\n return makeVecProxy(\n scalarNode(baseOffset, contiguous),\n componentSize,\n vecComponentCount,\n );\n }\n\n if (isWgslStruct(unwrapped)) {\n return makeStructProxy(unwrapped, scalarNode(baseOffset, contiguous));\n }\n\n if (isWgslArray(unwrapped)) {\n return makeArrayProxy(unwrapped, scalarNode(baseOffset, contiguous));\n }\n\n return scalarNode(baseOffset, contiguous);\n}\n\nexport function createOffsetProxy<T extends BaseData>(\n schema: T,\n baseOffset = 0,\n): unknown {\n return makeProxy(schema as AnyWgslData, baseOffset, sizeOf(schema));\n}\n\nfunction makeVecProxy(\n target: OffsetProxy,\n componentSize: number,\n componentCount: 2 | 3 | 4,\n): unknown {\n const baseOffset = target[OFFSET_MARKER];\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n const idx = prop === 'x' || prop === '0'\n ? 0\n : prop === 'y' || prop === '1'\n ? 1\n : prop === 'z' || prop === '2'\n ? 2\n : prop === 'w' || prop === '3'\n ? 3\n : -1;\n\n if (idx < 0 || idx >= componentCount) {\n return undefined;\n }\n\n const byteOffset = idx * componentSize;\n const contiguous = Math.max(0, t[CONTIGUOUS_MARKER] - byteOffset);\n\n return scalarNode(baseOffset + byteOffset, contiguous);\n },\n });\n}\n\nfunction makeArrayProxy(array: WgslArray, target: OffsetProxy): unknown {\n const elementType = array.elementType as AnyWgslData;\n const elementSize = sizeOf(elementType);\n const stride = roundUp(elementSize, alignmentOf(elementType));\n const hasPadding = stride > elementSize;\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n if (prop === 'length') {\n return array.elementCount;\n }\n\n if (typeof prop !== 'string') {\n return undefined;\n }\n\n const index = Number(prop);\n if (\n !Number.isInteger(index) ||\n index < 0 || index >= array.elementCount\n ) {\n return undefined;\n }\n\n const elementOffset = index * stride;\n const remainingFromHere = !isContiguous(elementType)\n ? elementSize + getLongestContiguousPrefix(elementType) // it is too much, but we correct it later\n : Math.max(\n 0,\n t[CONTIGUOUS_MARKER] - elementOffset,\n );\n\n const childContiguous = hasPadding\n ? Math.min(remainingFromHere, elementSize)\n : remainingFromHere;\n\n return makeProxy(\n elementType,\n t[OFFSET_MARKER] + elementOffset,\n childContiguous,\n );\n },\n });\n}\n\ntype StructFieldMeta = {\n offset: number;\n runEnd: number;\n};\n\nfunction makeStructProxy(struct: WgslStruct, target: OffsetProxy): unknown {\n const offsets = offsetsForProps(struct);\n const propTypes = struct.propTypes as Record<string, AnyWgslData>;\n const propNames = Object.keys(propTypes);\n\n const meta = new Map<string, StructFieldMeta>();\n\n let runStart = 0;\n for (let i = 0; i < propNames.length; i++) {\n const name = propNames[i];\n if (!name) {\n continue;\n }\n const type = propTypes[name];\n if (!type) {\n continue;\n }\n\n const info = offsets[name] as PropOffsetInfo;\n const padding = info.padding ?? 0;\n\n const typeContiguous = isContiguous(type);\n const isRunEnd = i === propNames.length - 1 || padding > 0 ||\n !typeContiguous;\n if (!isRunEnd) {\n continue;\n }\n\n const runEnd = info.offset +\n (typeContiguous ? info.size : getLongestContiguousPrefix(type));\n for (let j = runStart; j <= i; j++) {\n const runName = propNames[j];\n if (!runName) {\n continue;\n }\n const runInfo = offsets[runName] as PropOffsetInfo;\n meta.set(runName, { offset: runInfo.offset, runEnd });\n }\n runStart = i + 1;\n }\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n if (typeof prop !== 'string') {\n return undefined;\n }\n\n const m = meta.get(prop);\n if (!m) {\n return undefined;\n }\n\n const remainingFromHere = Math.max(\n 0,\n t[CONTIGUOUS_MARKER] - m.offset,\n );\n const localLimit = Math.max(0, m.runEnd - m.offset);\n const propSchema = propTypes[prop];\n if (!propSchema) {\n return undefined;\n }\n\n return makeProxy(\n propSchema,\n t[OFFSET_MARKER] + m.offset,\n sizeOf(struct) === m.runEnd ? remainingFromHere : localLimit,\n );\n },\n });\n}\n\nfunction getRootContiguous(schema: AnyWgslData): number {\n const unwrapped = undecorate(schema);\n\n if (isWgslStruct(unwrapped)) {\n const offsets = offsetsForProps(unwrapped);\n const propTypes = unwrapped.propTypes as Record<string, AnyWgslData>;\n const propNames = Object.keys(propTypes);\n\n for (let i = 0; i < propNames.length; i++) {\n const name = propNames[i];\n if (!name) {\n continue;\n }\n const info = offsets[name] as PropOffsetInfo;\n const padding = info.padding ?? 0;\n\n const runEnd = info.offset + info.size;\n const isRunEnd = i === propNames.length - 1 || padding > 0;\n if (isRunEnd) {\n return runEnd;\n }\n }\n\n return 0;\n }\n\n if (isWgslArray(unwrapped)) {\n const elementType = unwrapped.elementType as AnyWgslData;\n const elementSize = sizeOf(elementType);\n const stride = roundUp(elementSize, alignmentOf(elementType));\n const totalSize = sizeOf(schema);\n if (!Number.isFinite(totalSize)) {\n return elementSize;\n }\n return stride > elementSize ? elementSize : totalSize;\n }\n\n return sizeOf(schema);\n}\n\n/**\n * Interface containing information about the offset and the available contiguous after a selected primitive.\n */\nexport interface PrimitiveOffsetInfo {\n /** The byte offset of the primitive within the buffer. */\n offset: number;\n /** The number of contiguous bytes available from the offset. */\n contiguous: number;\n}\n\n/**\n * A function that retrieves offset and information for a specific primitive within a data schema.\n * Example usage:\n * ```ts\n * const Boid = d.struct({\n * position: d.vec3f,\n * velocity: d.vec3f,\n * });\n * const memLayout = d.memoryLayoutOf(Boid, (b) => b.velocity.y);\n * console.log(memLayout.offset); // Byte offset of velocity.y within Boid (here 20 bytes)\n * console.log(memLayout.contiguous); // Contiguous bytes available from that offset (here 8 bytes)\n * ```\n *\n * @param schema - The data schema to analyze.\n * @param accessor - Optional function that accesses a specific primitive within the schema. If omitted, uses the root offset (0).\n * @returns An object containing the offset and contiguous byte information.\n */\nexport function memoryLayoutOf<T extends BaseData>(\n schema: T,\n accessor?: (proxy: Infer<T>) => number,\n): PrimitiveOffsetInfo {\n if (!accessor) {\n return {\n offset: 0,\n contiguous: getRootContiguous(schema as AnyWgslData),\n };\n }\n\n const proxy = createOffsetProxy(schema);\n const result = accessor(proxy as Infer<T>);\n\n if (isOffsetProxy(result)) {\n return {\n offset: result[OFFSET_MARKER],\n contiguous: result[CONTIGUOUS_MARKER],\n };\n }\n\n throw new Error(\n 'Invalid accessor result. Expected an offset proxy with markers.',\n );\n}\n","import { comptime } from '../core/function/comptime.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport type { AnyData, Disarray } from './dataTypes.ts';\nimport { schemaCallWrapper } from './schemaCallWrapper.ts';\n\n// ----------\n// Public API\n// ----------\n\ninterface DisarrayConstructor {\n <TElement extends AnyData>(\n elementType: TElement,\n ): (elementCount: number) => Disarray<TElement>;\n\n <TElement extends AnyData>(\n elementType: TElement,\n elementCount: number,\n ): Disarray<TElement>;\n}\n\n/**\n * Creates an array schema that can be used to construct vertex buffers.\n * Describes arrays with fixed-size length, storing elements of the same type.\n *\n * Elements in the schema are not aligned in respect to their `byteAlignment`,\n * unless they are explicitly decorated with the custom align attribute\n * via `d.align` function.\n *\n * @example\n * const disarray = d.disarrayOf(d.vec3f, 3); // packed array of vec3f\n *\n * @example\n * const disarray = d.disarrayOf(d.align(16, d.vec3f), 3);\n *\n * If `elementCount` is not specified, a partially applied function is returned.\n * @example\n * const disarray = d.disarrayOf(d.vec3f);\n * // ^? (n: number) => Disarray<d.Vec3f>\n *\n * @param elementType The type of elements in the array.\n * @param elementCount The number of elements in the array.\n */\nexport const disarrayOf = comptime(\n ((elementType, elementCount) => {\n if (elementCount === undefined) {\n return (count: number) => cpu_disarrayOf(elementType, count);\n }\n return cpu_disarrayOf(elementType, elementCount);\n }) as DisarrayConstructor,\n).$name('disarrayOf');\n\nexport function cpu_disarrayOf<TElement extends AnyData>(\n elementType: TElement,\n elementCount: number,\n): Disarray<TElement> {\n // In the schema call, create and return a deep copy\n // by wrapping all the values in `elementType` schema calls.\n const disarraySchema = (elements?: TElement[]) => {\n if (elements && elements.length !== elementCount) {\n throw new Error(\n `Disarray schema of ${elementCount} elements of type ${elementType.type} called with ${elements.length} argument(s).`,\n );\n }\n\n return Array.from(\n { length: elementCount },\n (_, i) => schemaCallWrapper(elementType, elements?.[i]),\n );\n };\n Object.setPrototypeOf(disarraySchema, DisarrayImpl);\n\n disarraySchema.elementType = elementType;\n\n if (!Number.isInteger(elementCount) || elementCount < 0) {\n throw new Error(\n `Cannot create disarray schema with invalid element count: ${elementCount}.`,\n );\n }\n disarraySchema.elementCount = elementCount;\n\n return disarraySchema as unknown as Disarray<TElement>;\n}\n\n// --------------\n// Implementation\n// --------------\n\nconst DisarrayImpl = {\n [$internal]: true,\n type: 'disarray',\n\n toString(this: Disarray): string {\n return `disarrayOf(${this.elementType}, ${this.elementCount})`;\n },\n};\n","import { getName, setName } from '../shared/meta.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport type { AnyData, Unstruct } from './dataTypes.ts';\nimport { schemaCallWrapper } from './schemaCallWrapper.ts';\n\n// ----------\n// Public API\n// ----------\n\n/**\n * Creates a loose struct schema that can be used to construct vertex buffers.\n * Describes structs with members of both loose and non-loose types.\n *\n * The order of members matches the passed in properties object.\n * Members are not aligned in respect to their `byteAlignment`,\n * unless they are explicitly decorated with the custom align attribute\n * via `d.align` function.\n *\n * @example\n * const CircleStruct = d.unstruct({ radius: d.f32, pos: d.vec3f }); // packed struct with no padding\n *\n * @example\n * const CircleStruct = d.unstruct({ radius: d.f32, pos: d.align(16, d.vec3f) });\n *\n * @param properties Record with `string` keys and `TgpuData` or `TgpuLooseData` values,\n * each entry describing one struct member.\n */\nexport function unstruct<TProps extends Record<string, AnyData>>(\n properties: TProps,\n): Unstruct<TProps> {\n // In the schema call, create and return a deep copy\n // by wrapping all the values in corresponding schema calls.\n const unstructSchema = (instanceProps?: TProps) =>\n Object.fromEntries(\n Object.entries(properties).map(([key, schema]) => [\n key,\n schemaCallWrapper(schema, instanceProps?.[key]),\n ]),\n );\n Object.setPrototypeOf(unstructSchema, UnstructImpl);\n unstructSchema.propTypes = properties;\n\n return unstructSchema as unknown as Unstruct<TProps>;\n}\n\n// --------------\n// Implementation\n// --------------\n\nconst UnstructImpl = {\n [$internal]: true,\n type: 'unstruct',\n\n $name(label: string) {\n setName(this, label);\n return this;\n },\n\n toString(): string {\n return `unstruct:${getName(this) ?? '<unnamed>'}`;\n },\n};\n","import type { AnyAttribute } from './attributes.ts';\nimport { isDisarray, isLooseDecorated, isUnstruct } from './dataTypes.ts';\nimport type { AnyData } from './dataTypes.ts';\nimport {\n isAtomic,\n isDecorated,\n isPtr,\n isWgslArray,\n isWgslStruct,\n} from './wgslTypes.ts';\n\n/**\n * Performs a deep comparison of two TypeGPU data schemas.\n *\n * @param a The first data schema to compare.\n * @param b The second data schema to compare.\n * @returns `true` if the schemas are deeply equal, `false` otherwise.\n *\n * @example\n * ```ts\n * import { vec3f, struct, deepEqual } from 'typegpu/data';\n *\n * const schema1 = struct({ a: vec3f });\n * const schema2 = struct({ a: vec3f });\n * const schema3 = struct({ b: vec3f });\n *\n * console.log(deepEqual(schema1, schema2)); // true\n * console.log(deepEqual(schema1, schema3)); // false\n * ```\n */\nexport function deepEqual(a: AnyData, b: AnyData): boolean {\n if (a === b) {\n return true;\n }\n\n if (a.type !== b.type) {\n return false;\n }\n\n if (\n (isWgslStruct(a) && isWgslStruct(b)) ||\n (isUnstruct(a) && isUnstruct(b))\n ) {\n const aProps = a.propTypes;\n const bProps = b.propTypes;\n const aKeys = Object.keys(aProps);\n const bKeys = Object.keys(bProps);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (let i = 0; i < aKeys.length; i++) {\n const keyA = aKeys[i];\n const keyB = bKeys[i];\n if (\n keyA !== keyB || !keyA || !keyB ||\n !deepEqual(aProps[keyA] as AnyData, bProps[keyB] as AnyData)\n ) {\n return false;\n }\n }\n return true;\n }\n\n if ((isWgslArray(a) && isWgslArray(b)) || (isDisarray(a) && isDisarray(b))) {\n return (\n a.elementCount === b.elementCount &&\n deepEqual(a.elementType as AnyData, b.elementType as AnyData)\n );\n }\n\n if (isPtr(a) && isPtr(b)) {\n return (\n a.addressSpace === b.addressSpace &&\n a.access === b.access &&\n deepEqual(a.inner as AnyData, b.inner as AnyData)\n );\n }\n\n if (isAtomic(a) && isAtomic(b)) {\n return deepEqual(a.inner, b.inner);\n }\n\n if (\n (isDecorated(a) && isDecorated(b)) ||\n (isLooseDecorated(a) && isLooseDecorated(b))\n ) {\n if (!deepEqual(a.inner as AnyData, b.inner as AnyData)) {\n return false;\n }\n if (a.attribs.length !== b.attribs.length) {\n return false;\n }\n\n // Create comparable string representations for each attribute\n const getAttrKey = (attr: unknown): string => {\n const anyAttr = attr as AnyAttribute;\n return `${anyAttr.type}(${(anyAttr.params ?? []).join(',')})`;\n };\n\n const attrsA = a.attribs.map(getAttrKey);\n const attrsB = b.attribs.map(getAttrKey);\n\n for (let i = 0; i < attrsA.length; i++) {\n if (attrsA[i] !== attrsB[i]) {\n return false;\n }\n }\n }\n\n // All other types have been checked for equality at the start\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"deepEqual-DQxK4vdp.js","names":[],"sources":["../src/data/sampler.ts","../src/data/alignIO.ts","../src/data/offsets.ts","../src/data/atomic.ts","../src/data/isContiguous.ts","../src/data/getLongestContiguousPrefix.ts","../src/data/offsetUtils.ts","../src/data/disarray.ts","../src/data/unstruct.ts","../src/data/deepEqual.ts"],"sourcesContent":["import { $internal, $repr } from '../shared/symbols.ts';\nimport type { BaseData } from './wgslTypes.ts';\n\nexport interface WgslSamplerProps {\n addressModeU?: GPUAddressMode;\n addressModeV?: GPUAddressMode;\n /**\n * Specifies the address modes for the texture width, height, and depth\n * coordinates, respectively.\n */\n addressModeW?: GPUAddressMode;\n /**\n * Specifies the sampling behavior when the sample footprint is smaller than or equal to one\n * texel.\n */\n magFilter?: GPUFilterMode;\n /**\n * Specifies the sampling behavior when the sample footprint is larger than one texel.\n */\n minFilter?: GPUFilterMode;\n /**\n * Specifies behavior for sampling between mipmap levels.\n */\n mipmapFilter?: GPUMipmapFilterMode;\n lodMinClamp?: number;\n /**\n * Specifies the minimum and maximum levels of detail, respectively, used internally when\n * sampling a texture.\n */\n lodMaxClamp?: number;\n /**\n * Specifies the maximum anisotropy value clamp used by the sampler. Anisotropic filtering is\n * enabled when {@link GPUSamplerDescriptor.maxAnisotropy} is > 1 and the implementation supports it.\n * Anisotropic filtering improves the image quality of textures sampled at oblique viewing\n * angles. Higher {@link GPUSamplerDescriptor.maxAnisotropy} values indicate the maximum ratio of\n * anisotropy supported when filtering.\n *\n * Most implementations support {@link GPUSamplerDescriptor.maxAnisotropy} values in range\n * between 1 and 16, inclusive. The used value of {@link GPUSamplerDescriptor.maxAnisotropy}\n * will be clamped to the maximum value that the platform supports.\n * The precise filtering behavior is implementation-dependent.\n */\n maxAnisotropy?: number;\n}\n\nexport interface WgslComparisonSamplerProps {\n compare: GPUCompareFunction;\n addressModeU?: GPUAddressMode;\n addressModeV?: GPUAddressMode;\n /**\n * Specifies the address modes for the texture width, height, and depth\n * coordinates, respectively.\n */\n addressModeW?: GPUAddressMode;\n /**\n * Specifies the sampling behavior when the sample footprint is smaller than or equal to one\n * texel.\n */\n magFilter?: GPUFilterMode;\n /**\n * Specifies the sampling behavior when the sample footprint is larger than one texel.\n */\n minFilter?: GPUFilterMode;\n /**\n * Specifies behavior for sampling between mipmap levels.\n */\n mipmapFilter?: GPUMipmapFilterMode;\n lodMinClamp?: number;\n /**\n * Specifies the minimum and maximum levels of detail, respectively, used internally when\n * sampling a texture.\n */\n lodMaxClamp?: number;\n /**\n * Specifies the maximum anisotropy value clamp used by the sampler. Anisotropic filtering is\n * enabled when {@link GPUSamplerDescriptor.maxAnisotropy} is > 1 and the implementation supports it.\n * Anisotropic filtering improves the image quality of textures sampled at oblique viewing\n * angles. Higher {@link GPUSamplerDescriptor.maxAnisotropy} values indicate the maximum ratio of\n * anisotropy supported when filtering.\n *\n * Most implementations support {@link GPUSamplerDescriptor.maxAnisotropy} values in range\n * between 1 and 16, inclusive. The used value of {@link GPUSamplerDescriptor.maxAnisotropy}\n * will be clamped to the maximum value that the platform supports.\n * The precise filtering behavior is implementation-dependent.\n */\n maxAnisotropy?: number;\n}\n\nexport interface sampler {\n [$internal]: true;\n type: 'sampler';\n}\n\nexport function sampler(): WgslSampler {\n return {\n [$internal]: {},\n type: 'sampler',\n [$repr]: undefined as unknown as sampler,\n };\n}\n\nexport interface comparisonSampler {\n [$internal]: Record<string, never>;\n type: 'sampler_comparison';\n}\n\nexport function comparisonSampler(): WgslComparisonSampler {\n return {\n [$internal]: {},\n type: 'sampler_comparison',\n [$repr]: undefined as unknown as comparisonSampler,\n };\n}\n\nexport interface WgslSampler extends BaseData {\n readonly [$repr]: sampler;\n readonly type: 'sampler';\n}\n\nexport interface WgslComparisonSampler extends BaseData {\n readonly [$repr]: comparisonSampler;\n readonly type: 'sampler_comparison';\n}\n\nexport function isWgslSampler(value: unknown): value is WgslSampler {\n return (\n !!(value as WgslSampler)[$internal] &&\n (value as WgslSampler).type === 'sampler'\n );\n}\n\nexport function isWgslComparisonSampler(\n value: unknown,\n): value is WgslComparisonSampler {\n return (\n !!(value as WgslComparisonSampler)[$internal] &&\n (value as WgslComparisonSampler).type === 'sampler_comparison'\n );\n}\n","import type { IMeasurer, ISerialInput, ISerialOutput } from 'typed-binary';\n\n/**\n * @param io the IO to align\n * @param baseAlignment must be power of 2\n */\nfunction alignIO(\n io: ISerialInput | ISerialOutput | IMeasurer,\n baseAlignment: number,\n) {\n const currentPos = 'size' in io ? io.size : io.currentByteOffset;\n\n const bitMask = baseAlignment - 1;\n const offset = currentPos & bitMask;\n\n if ('skipBytes' in io) {\n io.skipBytes((baseAlignment - offset) & bitMask);\n } else {\n io.add((baseAlignment - offset) & bitMask);\n }\n}\n\nexport default alignIO;\n","import { Measurer } from 'typed-binary';\nimport { roundUp } from '../mathUtils.ts';\nimport alignIO from './alignIO.ts';\nimport { alignmentOf, customAlignmentOf } from './alignmentOf.ts';\nimport { isUnstruct, type Unstruct } from './dataTypes.ts';\nimport { sizeOf } from './sizeOf.ts';\nimport type { WgslStruct } from './wgslTypes.ts';\n\nexport interface OffsetInfo {\n offset: number;\n size: number;\n padding?: number | undefined;\n}\n\nconst cachedOffsets = new WeakMap<\n WgslStruct | Unstruct,\n Record<string, OffsetInfo>\n>();\n\nexport function offsetsForProps<T extends WgslStruct | Unstruct>(\n struct: T,\n): Record<keyof T['propTypes'], OffsetInfo> {\n type Key = keyof T['propTypes'];\n\n const cached = cachedOffsets.get(struct);\n if (cached) {\n return cached as Record<Key, OffsetInfo>;\n }\n\n const measurer = new Measurer();\n const offsets = {} as Record<Key, OffsetInfo>;\n let lastEntry: OffsetInfo | undefined;\n\n for (const key in struct.propTypes) {\n const prop = struct.propTypes[key];\n if (prop === undefined) {\n throw new Error(`Property ${key} is undefined in struct`);\n }\n\n const beforeAlignment = measurer.size;\n\n alignIO(\n measurer,\n isUnstruct(struct) ? customAlignmentOf(prop) : alignmentOf(prop),\n );\n\n if (lastEntry) {\n lastEntry.padding = measurer.size - beforeAlignment;\n }\n\n const propSize = sizeOf(prop);\n offsets[key as Key] = { offset: measurer.size, size: propSize };\n lastEntry = offsets[key];\n measurer.add(propSize);\n }\n\n if (lastEntry) {\n lastEntry.padding = roundUp(sizeOf(struct), alignmentOf(struct)) -\n measurer.size;\n }\n\n cachedOffsets.set(struct, offsets);\n return offsets;\n}\n","import type { Infer, MemIdentity } from '../shared/repr.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport {\n $gpuRepr,\n $memIdent,\n $repr,\n $validStorageSchema,\n $validUniformSchema,\n $validVertexSchema,\n} from '../shared/symbols.ts';\nimport type { Atomic, atomicI32, atomicU32, I32, U32 } from './wgslTypes.ts';\n\n// ----------\n// Public API\n// ----------\n\n/**\n * Marks a concrete integer scalar type schema (u32 or i32) as a WGSL atomic.\n *\n * @example\n * const atomicU32 = d.atomic(d.u32);\n * const atomicI32 = d.atomic(d.i32);\n *\n * @param data Underlying type schema.\n */\nexport function atomic<TSchema extends U32 | I32>(\n data: TSchema,\n): Atomic<TSchema> {\n return new AtomicImpl(data);\n}\n\n// --------------\n// Implementation\n// --------------\n\nclass AtomicImpl<TSchema extends U32 | I32> implements Atomic<TSchema> {\n public readonly [$internal] = {};\n public readonly type = 'atomic';\n\n // Type-tokens, not available at runtime\n declare readonly [$repr]: Infer<TSchema>;\n declare readonly [$memIdent]: MemIdentity<TSchema>;\n declare readonly [$gpuRepr]: TSchema extends U32 ? atomicU32 : atomicI32;\n declare readonly [$validStorageSchema]: true;\n declare readonly [$validUniformSchema]: true;\n declare readonly [$validVertexSchema]: true;\n // ---\n\n constructor(public readonly inner: TSchema) {}\n}\n","import type { AnyData } from './dataTypes.ts';\nimport type { BaseData } from './wgslTypes.ts';\nimport { getLayoutInfo } from './schemaMemoryLayout.ts';\n\nexport function isContiguous(schema: BaseData): boolean {\n return getLayoutInfo(schema, 'isContiguous');\n}\n\n/**\n * Returns `true` if data represented by the `schema` doesn't have padding.\n */\nexport function PUBLIC_isContiguous(schema: AnyData): boolean {\n return isContiguous(schema);\n}\n","import type { AnyData } from './dataTypes.ts';\nimport type { BaseData } from './wgslTypes.ts';\nimport { getLayoutInfo } from './schemaMemoryLayout.ts';\n\nexport function getLongestContiguousPrefix(schema: BaseData): number {\n return getLayoutInfo(schema, 'longestContiguousPrefix');\n}\n\n/**\n * Returns the size (in bytes) of the longest contiguous memory prefix of data represented by the `schema`.\n */\nexport function PUBLIC_getLongestContiguousPrefix(schema: AnyData): number {\n return getLongestContiguousPrefix(schema);\n}\n","import { roundUp } from '../mathUtils.ts';\nimport { alignmentOf } from './alignmentOf.ts';\nimport {\n type OffsetInfo as PropOffsetInfo,\n offsetsForProps,\n} from './offsets.ts';\nimport { sizeOf } from './sizeOf.ts';\nimport { isContiguous } from './isContiguous.ts';\nimport { getLongestContiguousPrefix } from './getLongestContiguousPrefix.ts';\nimport type {\n AnyWgslData,\n BaseData,\n VecData,\n WgslArray,\n WgslStruct,\n} from './wgslTypes.ts';\nimport { isVec, isWgslArray, isWgslStruct } from './wgslTypes.ts';\nimport { undecorate } from './dataTypes.ts';\nimport type { Infer } from '../shared/repr.ts';\n\nconst OFFSET_MARKER = Symbol('indirectOffset');\nconst CONTIGUOUS_MARKER = Symbol('indirectContiguous');\n\ninterface OffsetProxy {\n [OFFSET_MARKER]: number;\n [CONTIGUOUS_MARKER]: number;\n}\n\nfunction isOffsetProxy(value: unknown): value is OffsetProxy {\n return (\n typeof value === 'object' &&\n value !== null &&\n OFFSET_MARKER in value &&\n CONTIGUOUS_MARKER in value\n );\n}\n\nfunction scalarNode(offset: number, contiguous: number): OffsetProxy {\n return { [OFFSET_MARKER]: offset, [CONTIGUOUS_MARKER]: contiguous };\n}\n\nfunction getMarker(target: OffsetProxy, prop: PropertyKey): number | undefined {\n if (prop === OFFSET_MARKER) {\n return target[OFFSET_MARKER];\n }\n if (prop === CONTIGUOUS_MARKER) {\n return target[CONTIGUOUS_MARKER];\n }\n return undefined;\n}\n\nfunction makeProxy(\n schema: AnyWgslData,\n baseOffset: number,\n contiguous = sizeOf(schema),\n): unknown {\n const unwrapped = undecorate(schema);\n\n const vecComponentCount = isVec(unwrapped)\n ? unwrapped.componentCount\n : undefined;\n\n if (vecComponentCount !== undefined) {\n const componentSize = sizeOf((unwrapped as VecData).primitive);\n return makeVecProxy(\n scalarNode(baseOffset, contiguous),\n componentSize,\n vecComponentCount,\n );\n }\n\n if (isWgslStruct(unwrapped)) {\n return makeStructProxy(unwrapped, scalarNode(baseOffset, contiguous));\n }\n\n if (isWgslArray(unwrapped)) {\n return makeArrayProxy(unwrapped, scalarNode(baseOffset, contiguous));\n }\n\n return scalarNode(baseOffset, contiguous);\n}\n\nexport function createOffsetProxy<T extends BaseData>(\n schema: T,\n baseOffset = 0,\n): unknown {\n return makeProxy(schema as AnyWgslData, baseOffset, sizeOf(schema));\n}\n\nfunction makeVecProxy(\n target: OffsetProxy,\n componentSize: number,\n componentCount: 2 | 3 | 4,\n): unknown {\n const baseOffset = target[OFFSET_MARKER];\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n const idx = prop === 'x' || prop === '0'\n ? 0\n : prop === 'y' || prop === '1'\n ? 1\n : prop === 'z' || prop === '2'\n ? 2\n : prop === 'w' || prop === '3'\n ? 3\n : -1;\n\n if (idx < 0 || idx >= componentCount) {\n return undefined;\n }\n\n const byteOffset = idx * componentSize;\n const contiguous = Math.max(0, t[CONTIGUOUS_MARKER] - byteOffset);\n\n return scalarNode(baseOffset + byteOffset, contiguous);\n },\n });\n}\n\nfunction makeArrayProxy(array: WgslArray, target: OffsetProxy): unknown {\n const elementType = array.elementType as AnyWgslData;\n const elementSize = sizeOf(elementType);\n const stride = roundUp(elementSize, alignmentOf(elementType));\n const hasPadding = stride > elementSize;\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n if (prop === 'length') {\n return array.elementCount;\n }\n\n if (typeof prop !== 'string') {\n return undefined;\n }\n\n const index = Number(prop);\n if (\n !Number.isInteger(index) ||\n index < 0 || index >= array.elementCount\n ) {\n return undefined;\n }\n\n const elementOffset = index * stride;\n const remainingFromHere = !isContiguous(elementType)\n ? elementSize + getLongestContiguousPrefix(elementType) // it is too much, but we correct it later\n : Math.max(\n 0,\n t[CONTIGUOUS_MARKER] - elementOffset,\n );\n\n const childContiguous = hasPadding\n ? Math.min(remainingFromHere, elementSize)\n : remainingFromHere;\n\n return makeProxy(\n elementType,\n t[OFFSET_MARKER] + elementOffset,\n childContiguous,\n );\n },\n });\n}\n\ntype StructFieldMeta = {\n offset: number;\n runEnd: number;\n};\n\nfunction makeStructProxy(struct: WgslStruct, target: OffsetProxy): unknown {\n const offsets = offsetsForProps(struct);\n const propTypes = struct.propTypes as Record<string, AnyWgslData>;\n const propNames = Object.keys(propTypes);\n\n const meta = new Map<string, StructFieldMeta>();\n\n let runStart = 0;\n for (let i = 0; i < propNames.length; i++) {\n const name = propNames[i];\n if (!name) {\n continue;\n }\n const type = propTypes[name];\n if (!type) {\n continue;\n }\n\n const info = offsets[name] as PropOffsetInfo;\n const padding = info.padding ?? 0;\n\n const typeContiguous = isContiguous(type);\n const isRunEnd = i === propNames.length - 1 || padding > 0 ||\n !typeContiguous;\n if (!isRunEnd) {\n continue;\n }\n\n const runEnd = info.offset +\n (typeContiguous ? info.size : getLongestContiguousPrefix(type));\n for (let j = runStart; j <= i; j++) {\n const runName = propNames[j];\n if (!runName) {\n continue;\n }\n const runInfo = offsets[runName] as PropOffsetInfo;\n meta.set(runName, { offset: runInfo.offset, runEnd });\n }\n runStart = i + 1;\n }\n\n return new Proxy(target, {\n get(t, prop) {\n const marker = getMarker(t, prop);\n if (marker !== undefined) {\n return marker;\n }\n\n if (typeof prop !== 'string') {\n return undefined;\n }\n\n const m = meta.get(prop);\n if (!m) {\n return undefined;\n }\n\n const remainingFromHere = Math.max(\n 0,\n t[CONTIGUOUS_MARKER] - m.offset,\n );\n const localLimit = Math.max(0, m.runEnd - m.offset);\n const propSchema = propTypes[prop];\n if (!propSchema) {\n return undefined;\n }\n\n return makeProxy(\n propSchema,\n t[OFFSET_MARKER] + m.offset,\n sizeOf(struct) === m.runEnd ? remainingFromHere : localLimit,\n );\n },\n });\n}\n\nfunction getRootContiguous(schema: AnyWgslData): number {\n const unwrapped = undecorate(schema);\n\n if (isWgslStruct(unwrapped)) {\n const offsets = offsetsForProps(unwrapped);\n const propTypes = unwrapped.propTypes as Record<string, AnyWgslData>;\n const propNames = Object.keys(propTypes);\n\n for (let i = 0; i < propNames.length; i++) {\n const name = propNames[i];\n if (!name) {\n continue;\n }\n const info = offsets[name] as PropOffsetInfo;\n const padding = info.padding ?? 0;\n\n const runEnd = info.offset + info.size;\n const isRunEnd = i === propNames.length - 1 || padding > 0;\n if (isRunEnd) {\n return runEnd;\n }\n }\n\n return 0;\n }\n\n if (isWgslArray(unwrapped)) {\n const elementType = unwrapped.elementType as AnyWgslData;\n const elementSize = sizeOf(elementType);\n const stride = roundUp(elementSize, alignmentOf(elementType));\n const totalSize = sizeOf(schema);\n if (!Number.isFinite(totalSize)) {\n return elementSize;\n }\n return stride > elementSize ? elementSize : totalSize;\n }\n\n return sizeOf(schema);\n}\n\n/**\n * Interface containing information about the offset and the available contiguous after a selected primitive.\n */\nexport interface PrimitiveOffsetInfo {\n /** The byte offset of the primitive within the buffer. */\n offset: number;\n /** The number of contiguous bytes available from the offset. */\n contiguous: number;\n}\n\n/**\n * A function that retrieves offset and information for a specific primitive within a data schema.\n * Example usage:\n * ```ts\n * const Boid = d.struct({\n * position: d.vec3f,\n * velocity: d.vec3f,\n * });\n * const memLayout = d.memoryLayoutOf(Boid, (b) => b.velocity.y);\n * console.log(memLayout.offset); // Byte offset of velocity.y within Boid (here 20 bytes)\n * console.log(memLayout.contiguous); // Contiguous bytes available from that offset (here 8 bytes)\n * ```\n *\n * @param schema - The data schema to analyze.\n * @param accessor - Optional function that accesses a specific primitive within the schema. If omitted, uses the root offset (0).\n * @returns An object containing the offset and contiguous byte information.\n */\nexport function memoryLayoutOf<T extends BaseData>(\n schema: T,\n accessor?: (proxy: Infer<T>) => number,\n): PrimitiveOffsetInfo {\n if (!accessor) {\n return {\n offset: 0,\n contiguous: getRootContiguous(schema as AnyWgslData),\n };\n }\n\n const proxy = createOffsetProxy(schema);\n const result = accessor(proxy as Infer<T>);\n\n if (isOffsetProxy(result)) {\n return {\n offset: result[OFFSET_MARKER],\n contiguous: result[CONTIGUOUS_MARKER],\n };\n }\n\n throw new Error(\n 'Invalid accessor result. Expected an offset proxy with markers.',\n );\n}\n","import { comptime } from '../core/function/comptime.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport type { AnyData, Disarray } from './dataTypes.ts';\nimport { schemaCallWrapper } from './schemaCallWrapper.ts';\n\n// ----------\n// Public API\n// ----------\n\ninterface DisarrayConstructor {\n <TElement extends AnyData>(\n elementType: TElement,\n ): (elementCount: number) => Disarray<TElement>;\n\n <TElement extends AnyData>(\n elementType: TElement,\n elementCount: number,\n ): Disarray<TElement>;\n}\n\n/**\n * Creates an array schema that can be used to construct vertex buffers.\n * Describes arrays with fixed-size length, storing elements of the same type.\n *\n * Elements in the schema are not aligned in respect to their `byteAlignment`,\n * unless they are explicitly decorated with the custom align attribute\n * via `d.align` function.\n *\n * @example\n * const disarray = d.disarrayOf(d.vec3f, 3); // packed array of vec3f\n *\n * @example\n * const disarray = d.disarrayOf(d.align(16, d.vec3f), 3);\n *\n * If `elementCount` is not specified, a partially applied function is returned.\n * @example\n * const disarray = d.disarrayOf(d.vec3f);\n * // ^? (n: number) => Disarray<d.Vec3f>\n *\n * @param elementType The type of elements in the array.\n * @param elementCount The number of elements in the array.\n */\nexport const disarrayOf = comptime(\n ((elementType, elementCount) => {\n if (elementCount === undefined) {\n return (count: number) => cpu_disarrayOf(elementType, count);\n }\n return cpu_disarrayOf(elementType, elementCount);\n }) as DisarrayConstructor,\n).$name('disarrayOf');\n\nexport function cpu_disarrayOf<TElement extends AnyData>(\n elementType: TElement,\n elementCount: number,\n): Disarray<TElement> {\n // In the schema call, create and return a deep copy\n // by wrapping all the values in `elementType` schema calls.\n const disarraySchema = (elements?: TElement[]) => {\n if (elements && elements.length !== elementCount) {\n throw new Error(\n `Disarray schema of ${elementCount} elements of type ${elementType.type} called with ${elements.length} argument(s).`,\n );\n }\n\n return Array.from(\n { length: elementCount },\n (_, i) => schemaCallWrapper(elementType, elements?.[i]),\n );\n };\n Object.setPrototypeOf(disarraySchema, DisarrayImpl);\n\n disarraySchema.elementType = elementType;\n\n if (!Number.isInteger(elementCount) || elementCount < 0) {\n throw new Error(\n `Cannot create disarray schema with invalid element count: ${elementCount}.`,\n );\n }\n disarraySchema.elementCount = elementCount;\n\n return disarraySchema as unknown as Disarray<TElement>;\n}\n\n// --------------\n// Implementation\n// --------------\n\nconst DisarrayImpl = {\n [$internal]: true,\n type: 'disarray',\n\n toString(this: Disarray): string {\n return `disarrayOf(${this.elementType}, ${this.elementCount})`;\n },\n};\n","import { getName, setName } from '../shared/meta.ts';\nimport { $internal } from '../shared/symbols.ts';\nimport type { AnyData, Unstruct } from './dataTypes.ts';\nimport { schemaCallWrapper } from './schemaCallWrapper.ts';\n\n// ----------\n// Public API\n// ----------\n\n/**\n * Creates a loose struct schema that can be used to construct vertex buffers.\n * Describes structs with members of both loose and non-loose types.\n *\n * The order of members matches the passed in properties object.\n * Members are not aligned in respect to their `byteAlignment`,\n * unless they are explicitly decorated with the custom align attribute\n * via `d.align` function.\n *\n * @example\n * const CircleStruct = d.unstruct({ radius: d.f32, pos: d.vec3f }); // packed struct with no padding\n *\n * @example\n * const CircleStruct = d.unstruct({ radius: d.f32, pos: d.align(16, d.vec3f) });\n *\n * @param properties Record with `string` keys and `TgpuData` or `TgpuLooseData` values,\n * each entry describing one struct member.\n */\nexport function unstruct<TProps extends Record<string, AnyData>>(\n properties: TProps,\n): Unstruct<TProps> {\n // In the schema call, create and return a deep copy\n // by wrapping all the values in corresponding schema calls.\n const unstructSchema = (instanceProps?: TProps) =>\n Object.fromEntries(\n Object.entries(properties).map(([key, schema]) => [\n key,\n schemaCallWrapper(schema, instanceProps?.[key]),\n ]),\n );\n Object.setPrototypeOf(unstructSchema, UnstructImpl);\n unstructSchema.propTypes = properties;\n\n return unstructSchema as unknown as Unstruct<TProps>;\n}\n\n// --------------\n// Implementation\n// --------------\n\nconst UnstructImpl = {\n [$internal]: true,\n type: 'unstruct',\n\n $name(label: string) {\n setName(this, label);\n return this;\n },\n\n toString(): string {\n return `unstruct:${getName(this) ?? '<unnamed>'}`;\n },\n};\n","import type { AnyAttribute } from './attributes.ts';\nimport { isDisarray, isLooseDecorated, isUnstruct } from './dataTypes.ts';\nimport type { AnyData } from './dataTypes.ts';\nimport {\n isAtomic,\n isDecorated,\n isPtr,\n isWgslArray,\n isWgslStruct,\n} from './wgslTypes.ts';\n\n/**\n * Performs a deep comparison of two TypeGPU data schemas.\n *\n * @param a The first data schema to compare.\n * @param b The second data schema to compare.\n * @returns `true` if the schemas are deeply equal, `false` otherwise.\n *\n * @example\n * ```ts\n * import { vec3f, struct, deepEqual } from 'typegpu/data';\n *\n * const schema1 = struct({ a: vec3f });\n * const schema2 = struct({ a: vec3f });\n * const schema3 = struct({ b: vec3f });\n *\n * console.log(deepEqual(schema1, schema2)); // true\n * console.log(deepEqual(schema1, schema3)); // false\n * ```\n */\nexport function deepEqual(a: AnyData, b: AnyData): boolean {\n if (a === b) {\n return true;\n }\n\n if (a.type !== b.type) {\n return false;\n }\n\n if (\n (isWgslStruct(a) && isWgslStruct(b)) ||\n (isUnstruct(a) && isUnstruct(b))\n ) {\n const aProps = a.propTypes;\n const bProps = b.propTypes;\n const aKeys = Object.keys(aProps);\n const bKeys = Object.keys(bProps);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (let i = 0; i < aKeys.length; i++) {\n const keyA = aKeys[i];\n const keyB = bKeys[i];\n if (\n keyA !== keyB || !keyA || !keyB ||\n !deepEqual(aProps[keyA] as AnyData, bProps[keyB] as AnyData)\n ) {\n return false;\n }\n }\n return true;\n }\n\n if ((isWgslArray(a) && isWgslArray(b)) || (isDisarray(a) && isDisarray(b))) {\n return (\n a.elementCount === b.elementCount &&\n deepEqual(a.elementType as AnyData, b.elementType as AnyData)\n );\n }\n\n if (isPtr(a) && isPtr(b)) {\n return (\n a.addressSpace === b.addressSpace &&\n a.access === b.access &&\n deepEqual(a.inner as AnyData, b.inner as AnyData)\n );\n }\n\n if (isAtomic(a) && isAtomic(b)) {\n return deepEqual(a.inner, b.inner);\n }\n\n if (\n (isDecorated(a) && isDecorated(b)) ||\n (isLooseDecorated(a) && isLooseDecorated(b))\n ) {\n if (!deepEqual(a.inner as AnyData, b.inner as AnyData)) {\n return false;\n }\n if (a.attribs.length !== b.attribs.length) {\n return false;\n }\n\n // Create comparable string representations for each attribute\n const getAttrKey = (attr: unknown): string => {\n const anyAttr = attr as AnyAttribute;\n return `${anyAttr.type}(${(anyAttr.params ?? []).join(',')})`;\n };\n\n const attrsA = a.attribs.map(getAttrKey);\n const attrsB = b.attribs.map(getAttrKey);\n\n for (let i = 0; i < attrsA.length; i++) {\n if (attrsA[i] !== attrsB[i]) {\n return false;\n }\n }\n }\n\n // All other types have been checked for equality at the start\n return true;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { At as stitch, B as vec2h, C as translation4, E as dualImpl, G as vec3h, Gn as isVecInstance, H as vec2u, J as vec4b, K as vec3i, Mt as getResolutionCtx, N as abstruct, Pn as isHalfPrecisionSchema, Q as vec4u, R as vec2b, S as scaling4, T as MissingCpuImplError, U as vec3b, Un as isVec, V as vec2i, Vn as isPtr, W as vec3f, X as vec4h, Y as vec4f, Z as vec4i, _ as mat4x4f, at as i32, b as rotationY4, c as bitcastU32toF32Impl, et as abstractFloat, ft as unify, g as mat3x3f, h as mat2x2f, ht as safeStringify, i as mul, it as f32, jn as isAtomic, kn as Void, l as bitcastU32toI32Impl, mn as snip, nt as bool, o as sub, or as $gpuCallable, pn as isSnippetNumeric, q as vec3u, qn as isWgslArray, rt as f16, s as VectorOps, sn as SignatureNotSupportedError, st as u32, tt as abstractInt, u as smoothstepScalar, w as comptime, wt as ptrFn, x as rotationZ4, xt as isRef, y as rotationX4, z as vec2f } from "./operators-HTxa_0k9.js";
2
- import { r as isWgslTexture } from "./texture-Dg5ybJro.js";
1
+ import { At as stitch, B as vec2h, C as translation4, E as dualImpl, G as vec3h, Gn as isVecInstance, H as vec2u, J as vec4b, K as vec3i, Mt as getResolutionCtx, N as abstruct, Pn as isHalfPrecisionSchema, Q as vec4u, R as vec2b, S as scaling4, T as MissingCpuImplError, U as vec3b, Un as isVec, V as vec2i, Vn as isPtr, W as vec3f, X as vec4h, Y as vec4f, Z as vec4i, _ as mat4x4f, at as i32, b as rotationY4, c as bitcastU32toF32Impl, et as abstractFloat, ft as unify, g as mat3x3f, h as mat2x2f, ht as safeStringify, i as mul, it as f32, jn as isAtomic, kn as Void, l as bitcastU32toI32Impl, mn as snip, nt as bool, o as sub, or as $gpuCallable, pn as isSnippetNumeric, q as vec3u, qn as isWgslArray, rt as f16, s as VectorOps, sn as SignatureNotSupportedError, st as u32, tt as abstractInt, u as smoothstepScalar, w as comptime, wt as ptrFn, x as rotationZ4, xt as isRef, y as rotationX4, z as vec2f } from "./operators-d-PMVTo7.js";
2
+ import { r as isWgslTexture } from "./texture-BagDrrks.js";
3
3
  import * as TB from "typed-binary";
4
4
 
5
5
  //#region src/core/texture/textureFormats.ts
@@ -2029,4 +2029,4 @@ const extensionEnabled = comptime((extensionName) => {
2029
2029
 
2030
2030
  //#endregion
2031
2031
  export { workgroupBarrier as $, extractBits as $t, textureSampleCompareLevel as A, sqrt as An, acos as At, fwidthCoarse as B, cosh as Bt, textureDimensions as C, reverseBits as Cn, pack4x8unorm as Ct, textureSampleBaseClampToEdge as D, sin as Dn, bitcastU32toI32 as Dt, textureSample as E, sign as En, bitcastU32toF32 as Et, dpdxFine as F, trunc as Fn, atan2 as Ft, atomicMax as G, degrees as Gt, atomicAdd as H, countOneBits as Ht, dpdy as I, getEffectiveSampleTypes as In, atanh as It, atomicStore as J, dot as Jt, atomicMin as K, determinant as Kt, dpdyCoarse as L, getTextureFormatInfo as Ln, ceil as Lt, textureStore as M, tan as Mn, asin as Mt, dpdx as N, tanh as Nn, asinh as Nt, textureSampleBias as O, sinh as On, arrayLength as Ot, dpdxCoarse as P, transpose as Pn, atan as Pt, textureBarrier as Q, exp2 as Qt, dpdyFine as R, clamp as Rt, subgroupXor as S, refract as Sn, pack2x16float as St, textureLoad as T, saturate as Tn, unpack4x8unorm as Tt, atomicAnd as U, countTrailingZeros as Ut, fwidthFine as V, countLeadingZeros as Vt, atomicLoad as W, cross as Wt, atomicXor as X, dot4U8Packed as Xt, atomicSub as Y, dot4I8Packed as Yt, storageBarrier as Z, exp as Zt, subgroupOr as _, normalize as _n, not as _t, subgroupAny as a, fract as an, discard as at, subgroupShuffleUp as b, radians as bn, wgslExtensionToFeatureName as bt, subgroupBroadcastFirst as c, inverseSqrt as cn, and as ct, subgroupExclusiveMul as d, log as dn, ge as dt, faceForward as en, rotateX4 as et, subgroupInclusiveAdd as f, log2 as fn, gt as ft, subgroupMul as g, modf as gn, ne as gt, subgroupMin as h, mix as hn, lt as ht, subgroupAnd as i, fma as in, translate4 as it, textureSampleLevel as j, step as jn, acosh as jt, textureSampleCompare as k, smoothstep as kn, abs as kt, subgroupElect as l, ldexp as ln, any as lt, subgroupMax as m, min as mn, le as mt, subgroupAdd as n, firstTrailingBit as nn, rotateZ4 as nt, subgroupBallot as o, frexp as on, all as ot, subgroupInclusiveMul as p, max as pn, isCloseTo as pt, atomicOr as q, distance as qt, subgroupAll as r, floor as rn, scale4 as rt, subgroupBroadcast as s, insertBits as sn, allEq as st, extensionEnabled as t, firstLeadingBit as tn, rotateY4 as tt, subgroupExclusiveAdd as u, length as un, eq as ut, subgroupShuffle as v, pow as vn, or as vt, textureGather as w, round as wn, unpack2x16float as wt, subgroupShuffleXor as x, reflect as xn, wgslExtensions as xt, subgroupShuffleDown as y, quantizeToF16 as yn, select as yt, fwidth as z, cos as zt };
2032
- //# sourceMappingURL=extensions-0SFbU9FH.js.map
2032
+ //# sourceMappingURL=extensions-DIVuAfBM.js.map