typegpu 0.10.2 → 0.11.0

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.
Files changed (211) hide show
  1. package/_virtual/_rolldown/runtime.js +6 -11
  2. package/builtin.js +1 -3
  3. package/common/fullScreenTriangle.d.ts +1 -5
  4. package/common/fullScreenTriangle.js +1 -3
  5. package/common/index.d.ts +3 -2
  6. package/common/index.js +6 -4
  7. package/common/writeSoA.d.ts +16 -0
  8. package/common/writeSoA.js +90 -0
  9. package/core/buffer/buffer.d.ts +12 -7
  10. package/core/buffer/buffer.js +102 -53
  11. package/core/buffer/bufferShorthand.d.ts +5 -5
  12. package/core/buffer/bufferShorthand.js +9 -5
  13. package/core/buffer/bufferUsage.d.ts +0 -2
  14. package/core/buffer/bufferUsage.js +6 -4
  15. package/core/constant/tgpuConstant.d.ts +2 -1
  16. package/core/constant/tgpuConstant.js +8 -7
  17. package/core/declare/tgpuDeclare.js +8 -9
  18. package/core/function/autoIO.d.ts +7 -6
  19. package/core/function/autoIO.js +1 -3
  20. package/core/function/comptime.js +1 -3
  21. package/core/function/createCallableSchema.js +4 -6
  22. package/core/function/dualImpl.js +1 -3
  23. package/core/function/entryInputRouter.js +39 -0
  24. package/core/function/extractArgs.js +2 -2
  25. package/core/function/fnCore.js +19 -8
  26. package/core/function/fnTypes.d.ts +14 -8
  27. package/core/function/ioSchema.js +24 -3
  28. package/core/function/shelllessImpl.js +1 -3
  29. package/core/function/templateUtils.js +1 -2
  30. package/core/function/tgpuComputeFn.d.ts +2 -3
  31. package/core/function/tgpuComputeFn.js +9 -16
  32. package/core/function/tgpuFn.d.ts +2 -2
  33. package/core/function/tgpuFn.js +1 -3
  34. package/core/function/tgpuFragmentFn.d.ts +5 -1
  35. package/core/function/tgpuFragmentFn.js +5 -10
  36. package/core/function/tgpuVertexFn.d.ts +4 -0
  37. package/core/function/tgpuVertexFn.js +6 -12
  38. package/core/pipeline/applyPipelineState.js +1 -3
  39. package/core/pipeline/computePipeline.d.ts +2 -6
  40. package/core/pipeline/computePipeline.js +64 -63
  41. package/core/pipeline/connectAttachmentToShader.js +1 -3
  42. package/core/pipeline/connectTargetsToShader.js +1 -3
  43. package/core/pipeline/limitsOverflow.js +1 -2
  44. package/core/pipeline/pipelineUtils.js +29 -0
  45. package/core/pipeline/renderPipeline.d.ts +23 -5
  46. package/core/pipeline/renderPipeline.js +32 -14
  47. package/core/pipeline/timeable.d.ts +0 -3
  48. package/core/pipeline/timeable.js +3 -9
  49. package/core/pipeline/typeGuards.js +1 -3
  50. package/core/querySet/querySet.d.ts +0 -2
  51. package/core/querySet/querySet.js +37 -36
  52. package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +1 -3
  53. package/core/resolve/externals.d.ts +0 -2
  54. package/core/resolve/externals.js +2 -4
  55. package/core/resolve/namespace.js +1 -3
  56. package/core/resolve/resolveData.js +1 -3
  57. package/core/resolve/stitch.js +1 -3
  58. package/core/resolve/tgpuResolve.d.ts +3 -1
  59. package/core/resolve/tgpuResolve.js +3 -5
  60. package/core/root/configurableImpl.js +2 -3
  61. package/core/root/init.d.ts +0 -5
  62. package/core/root/init.js +35 -28
  63. package/core/root/rootTypes.d.ts +25 -5
  64. package/core/sampler/sampler.d.ts +0 -4
  65. package/core/sampler/sampler.js +3 -3
  66. package/core/simulate/tgpuSimulate.js +1 -3
  67. package/core/slot/accessor.d.ts +0 -4
  68. package/core/slot/accessor.js +1 -3
  69. package/core/slot/internalSlots.js +1 -3
  70. package/core/slot/lazy.js +1 -3
  71. package/core/slot/slot.js +2 -3
  72. package/core/slot/slotTypes.js +1 -3
  73. package/core/texture/externalTexture.d.ts +0 -6
  74. package/core/texture/externalTexture.js +2 -3
  75. package/core/texture/texture.d.ts +0 -4
  76. package/core/texture/texture.js +5 -3
  77. package/core/texture/textureFormats.js +1 -3
  78. package/core/texture/textureUtils.js +1 -3
  79. package/core/texture/usageExtension.js +1 -3
  80. package/core/unroll/tgpuUnroll.d.ts +58 -3
  81. package/core/unroll/tgpuUnroll.js +63 -5
  82. package/core/valueProxyUtils.js +1 -3
  83. package/core/variable/tgpuVariable.js +1 -3
  84. package/core/vertexLayout/connectAttributesToShader.js +1 -3
  85. package/core/vertexLayout/vertexLayout.js +9 -9
  86. package/data/alignIO.js +1 -2
  87. package/data/alignmentOf.d.ts +0 -1
  88. package/data/alignmentOf.js +1 -3
  89. package/data/array.d.ts +1 -3
  90. package/data/array.js +2 -4
  91. package/data/atomic.js +2 -3
  92. package/data/attributes.js +3 -3
  93. package/data/autoStruct.d.ts +1 -3
  94. package/data/autoStruct.js +1 -3
  95. package/data/compiledIO.js +83 -86
  96. package/data/dataIO.js +46 -39
  97. package/data/dataTypes.d.ts +7 -7
  98. package/data/dataTypes.js +6 -3
  99. package/data/deepEqual.js +1 -3
  100. package/data/disarray.d.ts +1 -3
  101. package/data/disarray.js +1 -3
  102. package/data/getLongestContiguousPrefix.d.ts +0 -1
  103. package/data/getLongestContiguousPrefix.js +1 -3
  104. package/data/index.d.ts +3 -3
  105. package/data/index.js +10 -3
  106. package/data/isContiguous.d.ts +0 -1
  107. package/data/isContiguous.js +1 -3
  108. package/data/matrix.d.ts +8 -10
  109. package/data/matrix.js +32 -18
  110. package/data/numberOps.js +1 -2
  111. package/data/numeric.js +16 -29
  112. package/data/offsetUtils.d.ts +2 -2
  113. package/data/offsetUtils.js +3 -5
  114. package/data/offsets.js +1 -3
  115. package/data/partialIO.js +84 -39
  116. package/data/ptr.d.ts +0 -1
  117. package/data/ptr.js +1 -3
  118. package/data/ref.d.ts +0 -3
  119. package/data/ref.js +1 -3
  120. package/data/sampler.js +1 -3
  121. package/data/schemaCallWrapper.js +1 -3
  122. package/data/schemaMemoryLayout.js +1 -3
  123. package/data/sizeOf.d.ts +0 -1
  124. package/data/sizeOf.js +1 -3
  125. package/data/snippet.js +12 -3
  126. package/data/struct.js +1 -3
  127. package/data/texture.js +1 -3
  128. package/data/unstruct.js +1 -3
  129. package/data/vector.js +4 -12
  130. package/data/vectorImpl.js +27 -28
  131. package/data/vectorOps.js +20 -3
  132. package/data/vertexFormatData.js +2 -3
  133. package/data/wgslTypes.d.ts +39 -11
  134. package/data/wgslTypes.js +10 -3
  135. package/errors.js +6 -3
  136. package/execMode.js +1 -3
  137. package/extension.js +1 -3
  138. package/getGPUValue.js +1 -3
  139. package/index.d.ts +4 -2
  140. package/index.js +3 -3
  141. package/indexNamedExports.d.ts +3 -1
  142. package/mathUtils.js +1 -2
  143. package/memo.js +8 -8
  144. package/nameRegistry.js +1 -3
  145. package/package.js +2 -3
  146. package/package.json +7 -7
  147. package/resolutionCtx.d.ts +0 -10
  148. package/resolutionCtx.js +84 -18
  149. package/shared/env.js +1 -2
  150. package/shared/generators.js +1 -2
  151. package/shared/meta.js +1 -3
  152. package/shared/repr.d.ts +32 -2
  153. package/shared/stringify.js +1 -3
  154. package/shared/symbols.d.ts +10 -1
  155. package/shared/symbols.js +10 -33
  156. package/shared/utilityTypes.d.ts +6 -2
  157. package/shared/utilityTypes.js +1 -2
  158. package/shared/vertexFormat.js +1 -2
  159. package/std/array.d.ts +1 -1
  160. package/std/array.js +1 -3
  161. package/std/atomic.d.ts +12 -12
  162. package/std/atomic.js +1 -3
  163. package/std/bitcast.d.ts +2 -2
  164. package/std/bitcast.js +1 -3
  165. package/std/boolean.d.ts +30 -16
  166. package/std/boolean.js +37 -12
  167. package/std/derivative.d.ts +9 -9
  168. package/std/derivative.js +1 -3
  169. package/std/discard.d.ts +1 -1
  170. package/std/discard.js +1 -3
  171. package/std/extensions.d.ts +1 -3
  172. package/std/extensions.js +1 -3
  173. package/std/index.d.ts +5 -4
  174. package/std/index.js +8 -5
  175. package/std/matrix.d.ts +5 -5
  176. package/std/matrix.js +1 -3
  177. package/std/numeric.d.ts +78 -132
  178. package/std/numeric.js +1 -3
  179. package/std/operators.d.ts +16 -8
  180. package/std/operators.js +80 -6
  181. package/std/packing.d.ts +4 -4
  182. package/std/packing.js +1 -3
  183. package/std/range.d.ts +24 -0
  184. package/std/range.js +38 -0
  185. package/std/subgroup.d.ts +21 -21
  186. package/std/subgroup.js +1 -3
  187. package/std/texture.d.ts +20 -11
  188. package/std/texture.js +13 -3
  189. package/tgpu.js +1 -3
  190. package/tgpuBindGroupLayout.js +9 -8
  191. package/tgpuUnstable.js +1 -3
  192. package/tgsl/accessIndex.js +2 -4
  193. package/tgsl/accessProp.js +8 -6
  194. package/tgsl/consoleLog/deserializers.js +1 -3
  195. package/tgsl/consoleLog/logGenerator.js +2 -4
  196. package/tgsl/consoleLog/serializers.js +24 -26
  197. package/tgsl/consoleLog/types.d.ts +0 -2
  198. package/tgsl/consoleLog/types.js +1 -2
  199. package/tgsl/conversion.js +1 -3
  200. package/tgsl/forOfUtils.js +35 -9
  201. package/tgsl/generationHelpers.js +3 -3
  202. package/tgsl/math.js +1 -3
  203. package/tgsl/shaderGenerator.d.ts +10 -8
  204. package/tgsl/shaderGenerator_members.d.ts +2 -0
  205. package/tgsl/shaderGenerator_members.js +6 -0
  206. package/tgsl/shellless.js +1 -8
  207. package/tgsl/wgslGenerator.d.ts +36 -0
  208. package/tgsl/wgslGenerator.js +144 -81
  209. package/types.d.ts +14 -4
  210. package/types.js +3 -3
  211. package/wgslExtensions.js +1 -2
@@ -2,17 +2,12 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __exportAll = (all, no_symbols) => {
4
4
  let target = {};
5
- for (var name in all) {
6
- __defProp(target, name, {
7
- get: all[name],
8
- enumerable: true
9
- });
10
- }
11
- if (!no_symbols) {
12
- __defProp(target, Symbol.toStringTag, { value: "Module" });
13
- }
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
14
10
  return target;
15
11
  };
16
-
17
12
  //#endregion
18
- export { __exportAll };
13
+ export { __exportAll };
package/builtin.js CHANGED
@@ -3,7 +3,6 @@ import { bool, f32, u32 } from "./data/numeric.js";
3
3
  import { vec3u, vec4f } from "./data/vector.js";
4
4
  import { attribute } from "./data/attributes.js";
5
5
  import { arrayOf } from "./data/array.js";
6
-
7
6
  //#region src/builtin.ts
8
7
  function defineBuiltin(dataType, value) {
9
8
  return attribute(dataType, {
@@ -32,6 +31,5 @@ const builtin = {
32
31
  subgroupId: defineBuiltin(u32, "subgroup_id"),
33
32
  numSubgroups: defineBuiltin(u32, "num_subgroups")
34
33
  };
35
-
36
34
  //#endregion
37
- export { builtin };
35
+ export { builtin };
@@ -1,7 +1,5 @@
1
1
  import { TgpuVertexFn } from "../core/function/tgpuVertexFn.js";
2
2
  import { Vec2f } from "../data/wgslTypes.js";
3
- import "../indexNamedExports.js";
4
-
5
3
  //#region src/common/fullScreenTriangle.d.ts
6
4
  /**
7
5
  * A vertex function that defines a single full-screen triangle out
@@ -19,8 +17,6 @@ import "../indexNamedExports.js";
19
17
  * pipeline.draw(3);
20
18
  * ```
21
19
  */
22
- declare const fullScreenTriangle: TgpuVertexFn<{}, {
23
- uv: Vec2f;
24
- }>;
20
+ declare const fullScreenTriangle: TgpuVertexFn;
25
21
  //#endregion
26
22
  export { fullScreenTriangle };
@@ -1,7 +1,6 @@
1
1
  import { vec2f } from "../data/vector.js";
2
2
  import { builtin } from "../builtin.js";
3
3
  import { vertexFn } from "../core/function/tgpuVertexFn.js";
4
-
5
4
  //#region src/common/fullScreenTriangle.ts
6
5
  /**
7
6
  * A vertex function that defines a single full-screen triangle out
@@ -31,6 +30,5 @@ const fullScreenTriangle = vertexFn({
31
30
 
32
31
  return Out(vec4f(pos[in.vertexIndex], 0, 1), uv[in.vertexIndex]);
33
32
  }`;
34
-
35
33
  //#endregion
36
- export { fullScreenTriangle };
34
+ export { fullScreenTriangle };
package/common/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { fullScreenTriangle } from "./fullScreenTriangle.js";
2
+ import { writeSoA } from "./writeSoA.js";
2
3
 
3
4
  //#region src/common/index.d.ts
4
5
  declare namespace index_d_exports {
5
- export { fullScreenTriangle };
6
+ export { fullScreenTriangle, writeSoA };
6
7
  }
7
8
  //#endregion
8
- export { fullScreenTriangle, index_d_exports };
9
+ export { fullScreenTriangle, index_d_exports, writeSoA };
package/common/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
2
  import { fullScreenTriangle } from "./fullScreenTriangle.js";
3
-
3
+ import { writeSoA } from "./writeSoA.js";
4
4
  //#region src/common/index.ts
5
- var common_exports = /* @__PURE__ */ __exportAll({ fullScreenTriangle: () => fullScreenTriangle });
6
-
5
+ var common_exports = /* @__PURE__ */ __exportAll({
6
+ fullScreenTriangle: () => fullScreenTriangle,
7
+ writeSoA: () => writeSoA
8
+ });
7
9
  //#endregion
8
- export { common_exports, fullScreenTriangle };
10
+ export { common_exports, fullScreenTriangle, writeSoA };
@@ -0,0 +1,16 @@
1
+ import { Prettify } from "../shared/utilityTypes.js";
2
+ import { BufferWriteOptions, TgpuBuffer } from "../core/buffer/buffer.js";
3
+ import { BaseData, TypedArrayFor, WgslArray, WgslStruct } from "../data/wgslTypes.js";
4
+ import { Undecorate } from "../data/dataTypes.js";
5
+
6
+ //#region src/common/writeSoA.d.ts
7
+ type PackedScalarFor<T> = Undecorate<T> extends WgslArray<infer TElement> ? PackedScalarFor<TElement> : Undecorate<T>;
8
+ type PackedSoAInputFor<T> = TypedArrayFor<PackedScalarFor<T>>;
9
+ type SoAFieldsFor<T extends Record<string, BaseData>> = { [K in keyof T as [PackedSoAInputFor<T[K]>] extends [never] ? never : K]: PackedSoAInputFor<T[K]> };
10
+ type SoAInputFor<T extends Record<string, BaseData>> = [keyof T] extends [keyof SoAFieldsFor<T>] ? Prettify<SoAFieldsFor<T>> : never;
11
+ declare function writeSoA<TProps extends Record<string, BaseData>>(buffer: TgpuBuffer<WgslArray<WgslStruct<TProps>>>, data: SoAInputFor<TProps>, options?: BufferWriteOptions): void;
12
+ declare namespace writeSoA {
13
+ type InputFor<TProps extends Record<string, BaseData>> = SoAInputFor<TProps>;
14
+ }
15
+ //#endregion
16
+ export { writeSoA };
@@ -0,0 +1,90 @@
1
+ import { isAtomic, isMat, isMat2x2f, isMat3x3f, isWgslArray } from "../data/wgslTypes.js";
2
+ import { undecorate } from "../data/dataTypes.js";
3
+ import { invariant } from "../errors.js";
4
+ import { alignmentOf } from "../data/alignmentOf.js";
5
+ import { roundUp } from "../mathUtils.js";
6
+ import { sizeOf } from "../data/sizeOf.js";
7
+ import { offsetsForProps } from "../data/offsets.js";
8
+ //#region src/common/writeSoA.ts
9
+ function packedSchemaOf(schema) {
10
+ const unpackedSchema = undecorate(schema);
11
+ return isAtomic(unpackedSchema) ? unpackedSchema.inner : unpackedSchema;
12
+ }
13
+ function packedMatrixDimOf(schema) {
14
+ return isMat3x3f(schema) ? 3 : isMat2x2f(schema) ? 2 : isMat(schema) ? 4 : void 0;
15
+ }
16
+ function packedSizeOf(schema) {
17
+ const packedSchema = packedSchemaOf(schema);
18
+ const matrixDim = packedMatrixDimOf(packedSchema);
19
+ if (matrixDim) return matrixDim * matrixDim * 4;
20
+ if (isWgslArray(packedSchema)) return packedSchema.elementCount * packedSizeOf(packedSchema.elementType);
21
+ return sizeOf(packedSchema);
22
+ }
23
+ function computeSoAByteLength(arraySchema, soaData) {
24
+ const structSchema = arraySchema.elementType;
25
+ let inferredCount;
26
+ for (const key in structSchema.propTypes) {
27
+ const srcArray = soaData[key];
28
+ const fieldSchema = structSchema.propTypes[key];
29
+ if (srcArray === void 0 || fieldSchema === void 0) continue;
30
+ const packedFieldSize = packedSizeOf(fieldSchema);
31
+ if (packedFieldSize === 0) continue;
32
+ const fieldElementCount = Math.floor(srcArray.byteLength / packedFieldSize);
33
+ inferredCount = inferredCount === void 0 ? fieldElementCount : Math.min(inferredCount, fieldElementCount);
34
+ }
35
+ if (inferredCount === void 0) return;
36
+ const elementStride = roundUp(sizeOf(structSchema), alignmentOf(structSchema));
37
+ return inferredCount * elementStride;
38
+ }
39
+ function writePackedValue(target, schema, srcBytes, dstOffset, srcOffset) {
40
+ const unpackedSchema = undecorate(schema);
41
+ const packedSchema = isAtomic(unpackedSchema) ? unpackedSchema.inner : unpackedSchema;
42
+ const matrixDim = packedMatrixDimOf(packedSchema);
43
+ if (matrixDim) {
44
+ const packedColumnSize = matrixDim * 4;
45
+ const gpuColumnStride = roundUp(packedColumnSize, alignmentOf(schema));
46
+ for (let col = 0; col < matrixDim; col++) target.set(srcBytes.subarray(srcOffset + col * packedColumnSize, srcOffset + col * packedColumnSize + packedColumnSize), dstOffset + col * gpuColumnStride);
47
+ return;
48
+ }
49
+ if (isWgslArray(unpackedSchema)) {
50
+ const packedElementSize = packedSizeOf(unpackedSchema.elementType);
51
+ const gpuElementStride = roundUp(sizeOf(unpackedSchema.elementType), alignmentOf(unpackedSchema.elementType));
52
+ for (let i = 0; i < unpackedSchema.elementCount; i++) writePackedValue(target, unpackedSchema.elementType, srcBytes, dstOffset + i * gpuElementStride, srcOffset + i * packedElementSize);
53
+ return;
54
+ }
55
+ target.set(srcBytes.subarray(srcOffset, srcOffset + sizeOf(packedSchema)), dstOffset);
56
+ }
57
+ function scatterSoA(target, arraySchema, soaData, startOffset, endOffset) {
58
+ const structSchema = arraySchema.elementType;
59
+ const elementStride = roundUp(sizeOf(structSchema), alignmentOf(structSchema));
60
+ invariant(startOffset % elementStride === 0, `startOffset (${startOffset}) must be aligned to the element stride (${elementStride})`);
61
+ const startElement = Math.floor(startOffset / elementStride);
62
+ const endElement = Math.min(arraySchema.elementCount, Math.ceil(endOffset / elementStride));
63
+ const elementCount = Math.max(0, endElement - startElement);
64
+ const offsets = offsetsForProps(structSchema);
65
+ for (const key in structSchema.propTypes) {
66
+ const fieldSchema = structSchema.propTypes[key];
67
+ if (fieldSchema === void 0) continue;
68
+ const srcArray = soaData[key];
69
+ invariant(srcArray !== void 0, `Missing SoA data for field '${key}'`);
70
+ const fieldOffset = offsets[key]?.offset;
71
+ invariant(fieldOffset !== void 0, `Field ${key} not found in struct schema`);
72
+ const packedFieldSize = packedSizeOf(fieldSchema);
73
+ const srcBytes = new Uint8Array(srcArray.buffer, srcArray.byteOffset, srcArray.byteLength);
74
+ for (let i = 0; i < elementCount; i++) writePackedValue(target, fieldSchema, srcBytes, (startElement + i) * elementStride + fieldOffset, i * packedFieldSize);
75
+ }
76
+ }
77
+ function writeSoA(buffer, data, options) {
78
+ const arrayBuffer = buffer.arrayBuffer;
79
+ const startOffset = options?.startOffset ?? 0;
80
+ const bufferSize = sizeOf(buffer.dataType);
81
+ const naturalSize = computeSoAByteLength(buffer.dataType, data);
82
+ const endOffset = options?.endOffset ?? (naturalSize === void 0 ? bufferSize : Math.min(startOffset + naturalSize, bufferSize));
83
+ scatterSoA(new Uint8Array(arrayBuffer), buffer.dataType, data, startOffset, endOffset);
84
+ buffer.write(arrayBuffer, {
85
+ startOffset,
86
+ endOffset
87
+ });
88
+ }
89
+ //#endregion
90
+ export { writeSoA };
@@ -3,11 +3,8 @@ import { $internal } from "../../shared/symbols.js";
3
3
  import { Prettify, UnionToIntersection } from "../../shared/utilityTypes.js";
4
4
  import { StorageFlag } from "../../extension.js";
5
5
  import { TgpuBufferMutable, TgpuBufferReadonly, TgpuBufferUniform, TgpuFixedBufferUsage } from "./bufferUsage.js";
6
- import "../root/rootTypes.js";
7
6
  import { BaseData } from "../../data/wgslTypes.js";
8
- import { Infer, InferPartial, IsValidIndexSchema, IsValidStorageSchema, IsValidUniformSchema, IsValidVertexSchema, MemIdentity } from "../../shared/repr.js";
9
- import "../../data/dataTypes.js";
10
-
7
+ import { Infer, InferInput, InferPartial, InferPatch, IsValidIndexSchema, IsValidStorageSchema, IsValidUniformSchema, IsValidVertexSchema, MemIdentity } from "../../shared/repr.js";
11
8
  //#region src/core/buffer/buffer.d.ts
12
9
  interface UniformFlag {
13
10
  usableAsUniform: true;
@@ -44,11 +41,16 @@ type InnerValidUsagesFor<T> = {
44
41
  usage: (IsValidStorageSchema<T> extends true ? 'storage' : never) | (IsValidUniformSchema<T> extends true ? 'uniform' : never) | (IsValidVertexSchema<T> extends true ? 'vertex' : never) | (IsValidIndexSchema<T> extends true ? 'index' : never) | 'indirect';
45
42
  };
46
43
  type ValidUsagesFor<T> = InnerValidUsagesFor<T>['usage'];
44
+ type BufferWriteOptions = {
45
+ startOffset?: number;
46
+ endOffset?: number;
47
+ };
47
48
  interface TgpuBuffer<TData extends BaseData> extends TgpuNamable {
48
49
  readonly [$internal]: true;
49
50
  readonly resourceType: 'buffer';
50
51
  readonly dataType: TData;
51
- readonly initial?: Infer<TData> | undefined;
52
+ readonly initial?: InferInput<TData> | undefined;
53
+ readonly arrayBuffer: ArrayBuffer;
52
54
  readonly buffer: GPUBuffer;
53
55
  readonly destroyed: boolean;
54
56
  usableAsUniform: boolean;
@@ -60,8 +62,11 @@ interface TgpuBuffer<TData extends BaseData> extends TgpuNamable {
60
62
  $addFlags(flags: GPUBufferUsageFlags): this;
61
63
  as<T extends ViewUsages<this>>(usage: T): UsageTypeToBufferUsage<TData>[T];
62
64
  compileWriter(): void;
63
- write(data: Infer<TData>): void;
65
+ write(data: InferInput<TData>, options?: BufferWriteOptions): void;
66
+ write(data: ArrayBuffer, options?: BufferWriteOptions): void;
67
+ /** @deprecated Use {@link patch} instead. */
64
68
  writePartial(data: InferPartial<TData>): void;
69
+ patch(data: InferPatch<TData>): void;
65
70
  clear(): void;
66
71
  copyFrom(srcBuffer: TgpuBuffer<MemIdentity<TData>>): void;
67
72
  read(): Promise<Infer<TData>>;
@@ -71,4 +76,4 @@ interface TgpuBuffer<TData extends BaseData> extends TgpuNamable {
71
76
  declare function isBuffer(value: unknown): value is TgpuBuffer<BaseData>;
72
77
  declare function isUsableAsVertex<T extends TgpuBuffer<BaseData>>(buffer: T): buffer is T & VertexFlag;
73
78
  //#endregion
74
- export { IndexFlag, IndirectFlag, TgpuBuffer, Uniform, UniformFlag, ValidUsagesFor, Vertex, VertexFlag, isBuffer, isUsableAsVertex };
79
+ export { BufferWriteOptions, IndexFlag, IndirectFlag, TgpuBuffer, Uniform, UniformFlag, ValidUsagesFor, Vertex, VertexFlag, isBuffer, isUsableAsVertex };
@@ -1,14 +1,15 @@
1
1
  import { $internal } from "../../shared/symbols.js";
2
2
  import { getName, setName } from "../../shared/meta.js";
3
- import { isWgslData } from "../../data/wgslTypes.js";
3
+ import { isWgslArray, isWgslData } from "../../data/wgslTypes.js";
4
4
  import { isGPUBuffer } from "../../types.js";
5
+ import { alignmentOf } from "../../data/alignmentOf.js";
6
+ import { roundUp } from "../../mathUtils.js";
5
7
  import { sizeOf } from "../../data/sizeOf.js";
6
- import { getCompiledWriterForSchema } from "../../data/compiledIO.js";
8
+ import { getCompiledWriter } from "../../data/compiledIO.js";
7
9
  import { readData, writeData } from "../../data/dataIO.js";
8
- import { getWriteInstructions } from "../../data/partialIO.js";
10
+ import { convertPartialToPatch, getPatchInstructions } from "../../data/partialIO.js";
9
11
  import { mutable, readonly, uniform } from "./bufferUsage.js";
10
12
  import { BufferReader, BufferWriter, getSystemEndianness } from "typed-binary";
11
-
12
13
  //#region src/core/buffer/buffer.ts
13
14
  const usageToUsageConstructor = {
14
15
  uniform,
@@ -30,57 +31,79 @@ var TgpuBufferImpl = class {
30
31
  [$internal] = true;
31
32
  resourceType = "buffer";
32
33
  flags = GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;
34
+ dataType;
33
35
  #device;
34
- _buffer = null;
35
- _ownBuffer;
36
- _destroyed = false;
37
- _hostBuffer;
36
+ #buffer = null;
37
+ #ownBuffer;
38
+ #destroyed = false;
39
+ #internalBuffer;
40
+ get #hostBuffer() {
41
+ return this.#internalBuffer ??= new ArrayBuffer(sizeOf(this.dataType));
42
+ }
43
+ #mappedRange;
44
+ #initialCallback;
45
+ #disallowedUsages;
38
46
  initial;
39
47
  usableAsUniform = false;
40
48
  usableAsStorage = false;
41
49
  usableAsVertex = false;
42
50
  usableAsIndex = false;
43
51
  usableAsIndirect = false;
44
- constructor(root, dataType, initialOrBuffer, _disallowedUsages) {
52
+ constructor(root, dataType, initialOrBuffer, disallowedUsages) {
45
53
  this.dataType = dataType;
46
- this.initialOrBuffer = initialOrBuffer;
47
- this._disallowedUsages = _disallowedUsages;
54
+ this.#disallowedUsages = disallowedUsages;
48
55
  this.#device = root.device;
49
56
  if (isGPUBuffer(initialOrBuffer)) {
50
- this._ownBuffer = false;
51
- this._buffer = initialOrBuffer;
57
+ this.#ownBuffer = false;
58
+ this.#buffer = initialOrBuffer;
52
59
  } else {
53
- this._ownBuffer = true;
54
- this.initial = initialOrBuffer;
60
+ this.#ownBuffer = true;
61
+ if (typeof initialOrBuffer === "function") this.#initialCallback = initialOrBuffer;
62
+ else this.initial = initialOrBuffer;
55
63
  }
56
64
  }
57
65
  get buffer() {
58
- if (this._destroyed) throw new Error("This buffer has been destroyed");
59
- if (!this._buffer) {
60
- this._buffer = this.#device.createBuffer({
66
+ if (this.#destroyed) throw new Error("This buffer has been destroyed");
67
+ if (!this.#buffer) {
68
+ this.#buffer = this.#device.createBuffer({
61
69
  size: sizeOf(this.dataType),
62
70
  usage: this.flags,
63
- mappedAtCreation: !!this.initial,
71
+ mappedAtCreation: !!this.initial || !!this.#initialCallback,
64
72
  label: getName(this) ?? "<unnamed>"
65
73
  });
66
- if (this.initial) {
67
- this._writeToTarget(this._buffer.getMappedRange(), this.initial);
68
- this._buffer.unmap();
74
+ if (this.initial || this.#initialCallback) {
75
+ if (this.#initialCallback) this.#initialCallback(this);
76
+ else if (this.initial) this.#writeToTarget(this.#getMappedRange(), this.initial);
77
+ this.#unmapBuffer();
69
78
  }
70
79
  }
71
- return this._buffer;
80
+ return this.#buffer;
72
81
  }
73
82
  get destroyed() {
74
- return this._destroyed;
83
+ return this.#destroyed;
84
+ }
85
+ get arrayBuffer() {
86
+ if (this.buffer.mapState === "mapped") return this.#getMappedRange();
87
+ return this.#hostBuffer;
88
+ }
89
+ #getMappedRange() {
90
+ if (!this.#buffer || this.#buffer.mapState !== "mapped") throw new Error("Buffer is not mapped.");
91
+ this.#mappedRange ??= this.#buffer.getMappedRange();
92
+ return this.#mappedRange;
93
+ }
94
+ #unmapBuffer() {
95
+ if (!this.#buffer || this.#buffer.mapState !== "mapped") return;
96
+ this.#mappedRange = void 0;
97
+ this.#buffer.unmap();
75
98
  }
76
99
  $name(label) {
77
100
  setName(this, label);
78
- if (this._buffer) this._buffer.label = label;
101
+ if (this.#buffer) this.#buffer.label = label;
79
102
  return this;
80
103
  }
81
104
  $usage(...usages) {
82
105
  for (const usage of usages) {
83
- if (this._disallowedUsages?.includes(usage)) throw new Error(`Buffer of type ${this.dataType.type} cannot be used as ${usage}`);
106
+ if (this.#disallowedUsages?.includes(usage)) throw new Error(`Buffer of type ${this.dataType.type} cannot be used as ${usage}`);
84
107
  this.flags |= usage === "uniform" ? GPUBufferUsage.UNIFORM : 0;
85
108
  this.flags |= usage === "storage" ? GPUBufferUsage.STORAGE : 0;
86
109
  this.flags |= usage === "vertex" ? GPUBufferUsage.VERTEX : 0;
@@ -95,7 +118,7 @@ var TgpuBufferImpl = class {
95
118
  return this;
96
119
  }
97
120
  $addFlags(flags) {
98
- if (!this._ownBuffer) throw new Error("Cannot add flags to a buffer that is not managed by TypeGPU.");
121
+ if (!this.#ownBuffer) throw new Error("Cannot add flags to a buffer that is not managed by TypeGPU.");
99
122
  if (flags & GPUBufferUsage.MAP_READ) {
100
123
  this.flags = GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ;
101
124
  return this;
@@ -108,43 +131,69 @@ var TgpuBufferImpl = class {
108
131
  return this;
109
132
  }
110
133
  compileWriter() {
111
- getCompiledWriterForSchema(this.dataType);
112
- }
113
- _writeToTarget(target, data) {
114
- const compiledWriter = getCompiledWriterForSchema(this.dataType);
134
+ getCompiledWriter(this.dataType);
135
+ }
136
+ #writeToTarget(target, data, options) {
137
+ const startOffset = options?.startOffset ?? 0;
138
+ const endOffset = options?.endOffset ?? target.byteLength;
139
+ if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
140
+ const src = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
141
+ const regionSize = endOffset - startOffset;
142
+ if (src.byteLength !== regionSize) console.warn(`Buffer size mismatch: expected ${regionSize} bytes, got ${src.byteLength}. ` + (src.byteLength < regionSize ? "Data truncated." : "Excess ignored."));
143
+ const copyLen = Math.min(src.byteLength, regionSize);
144
+ new Uint8Array(target).set(src.subarray(0, copyLen), startOffset);
145
+ return;
146
+ }
147
+ const dataView = new DataView(target);
148
+ const isLittleEndian = endianness === "little";
149
+ const compiledWriter = getCompiledWriter(this.dataType);
115
150
  if (compiledWriter) try {
116
- compiledWriter(new DataView(target), 0, data, endianness === "little");
151
+ compiledWriter(dataView, startOffset, data, isLittleEndian, endOffset);
117
152
  return;
118
153
  } catch (error) {
119
154
  console.error(`Error when using compiled writer for buffer ${getName(this) ?? "<unnamed>"} - this is likely a bug, please submit an issue at https://github.com/software-mansion/TypeGPU/issues\nUsing fallback writer instead.`, error);
120
155
  }
121
- writeData(new BufferWriter(target), this.dataType, data);
156
+ const writer = new BufferWriter(target);
157
+ writer.seekTo(startOffset);
158
+ writeData(writer, this.dataType, data);
122
159
  }
123
- write(data) {
160
+ write(data, options) {
124
161
  const gpuBuffer = this.buffer;
162
+ const bufferSize = sizeOf(this.dataType);
163
+ const startOffset = options?.startOffset ?? 0;
164
+ let naturalSize = void 0;
165
+ if (isWgslArray(this.dataType) && Array.isArray(data)) naturalSize = data.length * roundUp(sizeOf(this.dataType.elementType), alignmentOf(this.dataType.elementType));
166
+ else if (ArrayBuffer.isView(data) || data instanceof ArrayBuffer) naturalSize = data.byteLength;
167
+ const naturalEndOffset = naturalSize !== void 0 ? Math.min(startOffset + naturalSize, bufferSize) : void 0;
168
+ const size = (options?.endOffset ?? naturalEndOffset ?? bufferSize) - startOffset;
125
169
  if (gpuBuffer.mapState === "mapped") {
126
- const mapped = gpuBuffer.getMappedRange();
127
- this._writeToTarget(mapped, data);
170
+ const mapped = this.#getMappedRange();
171
+ if (data instanceof ArrayBuffer && data === mapped) return;
172
+ this.#writeToTarget(mapped, data, options);
128
173
  return;
129
174
  }
130
- const size = sizeOf(this.dataType);
131
- if (!this._hostBuffer) this._hostBuffer = new ArrayBuffer(size);
132
- this._writeToTarget(this._hostBuffer, data);
133
- this.#device.queue.writeBuffer(gpuBuffer, 0, this._hostBuffer, 0, size);
175
+ if (!(data instanceof ArrayBuffer && data === this.#hostBuffer)) this.#writeToTarget(this.#hostBuffer, data, options);
176
+ this.#device.queue.writeBuffer(gpuBuffer, startOffset, this.#hostBuffer, startOffset, size);
134
177
  }
178
+ /** @deprecated Use {@link patch} instead. */
135
179
  writePartial(data) {
180
+ this.#applyInstructions(getPatchInstructions(this.dataType, convertPartialToPatch(this.dataType, data), this.#hostBuffer));
181
+ }
182
+ patch(data) {
183
+ this.#applyInstructions(getPatchInstructions(this.dataType, data, this.#hostBuffer));
184
+ }
185
+ #applyInstructions(instructions) {
136
186
  const gpuBuffer = this.buffer;
137
- const instructions = getWriteInstructions(this.dataType, data);
138
187
  if (gpuBuffer.mapState === "mapped") {
139
- const mappedRange = gpuBuffer.getMappedRange();
188
+ const mappedRange = this.#getMappedRange();
140
189
  const mappedView = new Uint8Array(mappedRange);
141
- for (const instruction of instructions) mappedView.set(instruction.data, instruction.data.byteOffset);
142
- } else for (const instruction of instructions) this.#device.queue.writeBuffer(gpuBuffer, instruction.data.byteOffset, instruction.data, 0, instruction.data.byteLength);
190
+ for (const { data, gpuOffset } of instructions) mappedView.set(data, gpuOffset);
191
+ } else for (const { data, gpuOffset } of instructions) this.#device.queue.writeBuffer(gpuBuffer, gpuOffset, data);
143
192
  }
144
193
  clear() {
145
194
  const gpuBuffer = this.buffer;
146
195
  if (gpuBuffer.mapState === "mapped") {
147
- new Uint8Array(gpuBuffer.getMappedRange()).fill(0);
196
+ new Uint8Array(this.#getMappedRange()).fill(0);
148
197
  return;
149
198
  }
150
199
  const encoder = this.#device.createCommandEncoder();
@@ -160,11 +209,11 @@ var TgpuBufferImpl = class {
160
209
  }
161
210
  async read() {
162
211
  const gpuBuffer = this.buffer;
163
- if (gpuBuffer.mapState === "mapped") return readData(new BufferReader(gpuBuffer.getMappedRange()), this.dataType);
212
+ if (gpuBuffer.mapState === "mapped") return readData(new BufferReader(this.#getMappedRange()), this.dataType);
164
213
  if (gpuBuffer.usage & GPUBufferUsage.MAP_READ) {
165
214
  await gpuBuffer.mapAsync(GPUMapMode.READ);
166
- const res = readData(new BufferReader(gpuBuffer.getMappedRange()), this.dataType);
167
- gpuBuffer.unmap();
215
+ const res = readData(new BufferReader(this.#getMappedRange()), this.dataType);
216
+ this.#unmapBuffer();
168
217
  return res;
169
218
  }
170
219
  const stagingBuffer = this.#device.createBuffer({
@@ -184,14 +233,14 @@ var TgpuBufferImpl = class {
184
233
  return usageToUsageConstructor[usage]?.(this);
185
234
  }
186
235
  destroy() {
187
- if (this._destroyed) return;
188
- this._destroyed = true;
189
- if (this._ownBuffer) this._buffer?.destroy();
236
+ if (this.#destroyed) return;
237
+ this.#destroyed = true;
238
+ this.#mappedRange = void 0;
239
+ if (this.#ownBuffer) this.#buffer?.destroy();
190
240
  }
191
241
  toString() {
192
242
  return `buffer:${getName(this) ?? "<unnamed>"}`;
193
243
  }
194
244
  };
195
-
196
245
  //#endregion
197
- export { INTERNAL_createBuffer, isBuffer, isUsableAsVertex };
246
+ export { INTERNAL_createBuffer, isBuffer, isUsableAsVertex };
@@ -1,17 +1,17 @@
1
1
  import { TgpuNamable } from "../../shared/meta.js";
2
2
  import { $gpuValueOf, $internal } from "../../shared/symbols.js";
3
3
  import { StorageFlag } from "../../extension.js";
4
- import "../../data/snippet.js";
5
- import { TgpuBuffer, UniformFlag } from "./buffer.js";
6
- import "../../types.js";
4
+ import { BufferWriteOptions, TgpuBuffer, UniformFlag } from "./buffer.js";
7
5
  import { BaseData } from "../../data/wgslTypes.js";
8
- import { Infer, InferGPU, InferPartial } from "../../shared/repr.js";
6
+ import { Infer, InferGPU, InferInput, InferPartial, InferPatch } from "../../shared/repr.js";
9
7
 
10
8
  //#region src/core/buffer/bufferShorthand.d.ts
11
9
  interface TgpuBufferShorthandBase<TData extends BaseData> extends TgpuNamable {
12
10
  readonly [$internal]: true;
13
- write(data: Infer<TData>): void;
11
+ write(data: InferInput<TData>, options?: BufferWriteOptions): void;
12
+ /** @deprecated Use {@link patch} instead. */
14
13
  writePartial(data: InferPartial<TData>): void;
14
+ patch(data: InferPatch<TData>): void;
15
15
  read(): Promise<Infer<TData>>;
16
16
  readonly [$gpuValueOf]: InferGPU<TData>;
17
17
  }
@@ -1,6 +1,5 @@
1
1
  import { $getNameForward, $gpuValueOf, $internal, $resolve } from "../../shared/symbols.js";
2
2
  import { getName, setName } from "../../shared/meta.js";
3
-
4
3
  //#region src/core/buffer/bufferShorthand.ts
5
4
  function isBufferShorthand(value) {
6
5
  return value instanceof TgpuBufferShorthandImpl;
@@ -8,6 +7,8 @@ function isBufferShorthand(value) {
8
7
  var TgpuBufferShorthandImpl = class {
9
8
  [$internal] = true;
10
9
  [$getNameForward];
10
+ resourceType;
11
+ buffer;
11
12
  #usage;
12
13
  constructor(resourceType, buffer) {
13
14
  this.resourceType = resourceType;
@@ -19,12 +20,16 @@ var TgpuBufferShorthandImpl = class {
19
20
  setName(this, label);
20
21
  return this;
21
22
  }
22
- write(data) {
23
- this.buffer.write(data);
23
+ write(data, options) {
24
+ this.buffer.write(data, options);
24
25
  }
26
+ /** @deprecated Use {@link patch} instead. */
25
27
  writePartial(data) {
26
28
  this.buffer.writePartial(data);
27
29
  }
30
+ patch(data) {
31
+ this.buffer.patch(data);
32
+ }
28
33
  read() {
29
34
  return this.buffer.read();
30
35
  }
@@ -44,6 +49,5 @@ var TgpuBufferShorthandImpl = class {
44
49
  return ctx.resolve(this.#usage);
45
50
  }
46
51
  };
47
-
48
52
  //#endregion
49
- export { TgpuBufferShorthandImpl, isBufferShorthand };
53
+ export { TgpuBufferShorthandImpl, isBufferShorthand };
@@ -1,7 +1,5 @@
1
1
  import { TgpuNamable } from "../../shared/meta.js";
2
2
  import { $gpuValueOf, $internal, $repr } from "../../shared/symbols.js";
3
- import "../../data/snippet.js";
4
- import "../../tgpuBindGroupLayout.js";
5
3
  import { TgpuBuffer, UniformFlag } from "./buffer.js";
6
4
  import { BindableBufferUsage } from "../../types.js";
7
5
  import { BaseData } from "../../data/wgslTypes.js";
@@ -8,7 +8,6 @@ import { schemaCallWrapper } from "../../data/schemaCallWrapper.js";
8
8
  import { assertExhaustive } from "../../shared/utilityTypes.js";
9
9
  import { valueProxyHandler } from "../valueProxyUtils.js";
10
10
  import { isUsableAsStorage } from "../../extension.js";
11
-
12
11
  //#region src/core/buffer/bufferUsage.ts
13
12
  function isUsableAsUniform(buffer) {
14
13
  return !!buffer.usableAsUniform;
@@ -20,6 +19,8 @@ const usageToVarTemplateMap = {
20
19
  };
21
20
  var TgpuFixedBufferImpl = class {
22
21
  resourceType = "buffer-usage";
22
+ usage;
23
+ buffer;
23
24
  [$internal];
24
25
  [$getNameForward];
25
26
  constructor(usage, buffer) {
@@ -90,11 +91,13 @@ var TgpuFixedBufferImpl = class {
90
91
  var TgpuLaidOutBufferImpl = class {
91
92
  [$internal];
92
93
  resourceType = "buffer-usage";
94
+ usage;
95
+ dataType;
93
96
  #membership;
94
97
  constructor(usage, dataType, membership) {
98
+ this[$internal] = { dataType };
95
99
  this.usage = usage;
96
100
  this.dataType = dataType;
97
- this[$internal] = { dataType };
98
101
  this.#membership = membership;
99
102
  setName(this, membership.key);
100
103
  }
@@ -158,6 +161,5 @@ function uniform(buffer) {
158
161
  }
159
162
  return usage;
160
163
  }
161
-
162
164
  //#endregion
163
- export { TgpuLaidOutBufferImpl, isUsableAsUniform, mutable, readonly, uniform };
165
+ export { TgpuLaidOutBufferImpl, isUsableAsUniform, mutable, readonly, uniform };
@@ -1,6 +1,6 @@
1
1
  import { TgpuNamable } from "../../shared/meta.js";
2
2
  import { $gpuValueOf, $internal } from "../../shared/symbols.js";
3
- import { BaseData } from "../../data/wgslTypes.js";
3
+ import { AnyWgslData, BaseData, WgslArray } from "../../data/wgslTypes.js";
4
4
  import { InferGPU } from "../../shared/repr.js";
5
5
  import { AnyData } from "../../data/dataTypes.js";
6
6
 
@@ -24,5 +24,6 @@ interface TgpuConst<TDataType extends BaseData = BaseData> extends TgpuNamable {
24
24
  * Creates a module constant with specified value.
25
25
  */
26
26
  declare function constant<TDataType extends AnyData>(dataType: TDataType, value: InferGPU<TDataType>): TgpuConst<TDataType>;
27
+ declare function constant<TElement extends AnyWgslData>(dataType: (elementCount: number) => WgslArray<TElement>, value: InferGPU<WgslArray<TElement>>): TgpuConst<WgslArray<TElement>>;
27
28
  //#endregion
28
29
  export { TgpuConst, constant };