typegpu 0.12.4 → 0.12.6

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 (78) hide show
  1. package/bin.mjs +39 -67
  2. package/common/index.d.ts +1 -0
  3. package/common/index.js +1 -0
  4. package/common/writeChannels.d.ts +31 -0
  5. package/common/writeChannels.js +32 -0
  6. package/core/commandEncoder/computePass.d.ts +13 -0
  7. package/core/commandEncoder/computePass.js +5 -2
  8. package/core/commandEncoder/renderPass.d.ts +18 -4
  9. package/core/commandEncoder/renderPass.js +6 -2
  10. package/core/declare/tgpuDeclare.d.ts +11 -0
  11. package/core/declare/tgpuDeclare.js +1 -1
  12. package/core/immediate/immediateVar.d.ts +52 -0
  13. package/core/immediate/immediateVar.js +149 -0
  14. package/core/pipeline/computePipeline.d.ts +23 -0
  15. package/core/pipeline/computePipeline.js +26 -9
  16. package/core/pipeline/drawState.d.ts +8 -4
  17. package/core/pipeline/drawState.js +41 -51
  18. package/core/pipeline/priors.js +1 -0
  19. package/core/pipeline/renderPipeline.d.ts +24 -1
  20. package/core/pipeline/renderPipeline.js +18 -1
  21. package/core/root/init.js +3 -0
  22. package/core/root/rootTypes.d.ts +11 -0
  23. package/core/slot/slotTypes.d.ts +2 -1
  24. package/core/texture/texture.d.ts +20 -14
  25. package/core/texture/texture.js +70 -65
  26. package/core/texture/textureUtils.d.ts +3 -6
  27. package/core/texture/textureUtils.js +142 -165
  28. package/core/texture/textureWrite.d.ts +61 -0
  29. package/core/texture/textureWrite.js +59 -0
  30. package/data/dataIO.d.ts +2 -2
  31. package/data/generalizeFn.d.ts +17 -1
  32. package/data/generalizeFn.js +39 -2
  33. package/data/snippet.d.ts +5 -1
  34. package/data/snippet.js +1 -0
  35. package/data/wgslTypes.d.ts +1 -1
  36. package/errors.d.ts +7 -0
  37. package/errors.js +15 -0
  38. package/indexNamedExports.d.ts +5 -2
  39. package/indexNamedExports.js +2 -1
  40. package/internal.d.ts +1 -1
  41. package/internal.js +1 -1
  42. package/package.json +2 -2
  43. package/resolutionCtx.d.ts +5 -0
  44. package/resolutionCtx.js +11 -0
  45. package/serial/restore.d.ts +3 -1
  46. package/serial/restore.js +2 -0
  47. package/shared/meta.js +1 -1
  48. package/shared/symbols.js +1 -1
  49. package/shared/tseynit.d.ts +1 -0
  50. package/shared/tseynit.js +39 -7
  51. package/shared/utilityTypes.d.ts +1 -1
  52. package/std/atomic.d.ts +13 -0
  53. package/std/atomic.js +63 -29
  54. package/std/bitcast.js +4 -0
  55. package/std/boolean.d.ts +1 -1
  56. package/std/boolean.js +35 -21
  57. package/std/derivative.js +17 -12
  58. package/std/index.d.ts +4 -4
  59. package/std/index.js +5 -5
  60. package/std/numeric.d.ts +5 -1
  61. package/std/numeric.js +75 -8
  62. package/std/operators.d.ts +2 -2
  63. package/std/operators.js +29 -17
  64. package/std/packing.d.ts +61 -1
  65. package/std/packing.js +214 -25
  66. package/std/subgroup.d.ts +4 -0
  67. package/std/subgroup.js +34 -0
  68. package/std/texture.d.ts +13 -0
  69. package/std/texture.js +48 -0
  70. package/tgpuUnstable.d.ts +1 -0
  71. package/tgpuUnstable.js +1 -0
  72. package/tgsl/conversion.d.ts +2 -0
  73. package/tgsl/conversion.js +3 -0
  74. package/tgsl/shaderGenerator.d.ts +1 -1
  75. package/tgsl/wgslGenerator.d.ts +5 -0
  76. package/tgsl/wgslGenerator.js +218 -50
  77. package/types.d.ts +9 -1
  78. package/types.js +5 -0
@@ -0,0 +1,59 @@
1
+ export function origin3d([x = 0, y = 0, z = 0] = []) {
2
+ return { x, y, z };
3
+ }
4
+ export function mipLevelSize({ size, dimension }, mipLevel) {
5
+ const scale = (value = 1) => Math.max(1, value >> mipLevel);
6
+ return [scale(size[0]), scale(size[1]), dimension === '3d' ? scale(size[2]) : (size[2] ?? 1)];
7
+ }
8
+ /** The size of the written region: `size`, or the rest of the mip level past `origin` */
9
+ export function writeRegionSize(texture, options) {
10
+ const [mipWidth, mipHeight] = mipLevelSize(texture, options.mipLevel ?? 0);
11
+ const [x = 0, y = 0] = options.origin ?? [];
12
+ const [width = mipWidth - x, height = mipHeight - y] = options.size ?? [];
13
+ return [width, height];
14
+ }
15
+ function imageSize(source) {
16
+ const { videoWidth, videoHeight } = source;
17
+ if (videoWidth && videoHeight) {
18
+ return [videoWidth, videoHeight];
19
+ }
20
+ const { naturalWidth, naturalHeight } = source;
21
+ if (naturalWidth && naturalHeight) {
22
+ return [naturalWidth, naturalHeight];
23
+ }
24
+ const { codedWidth, codedHeight } = source;
25
+ if (codedWidth && codedHeight) {
26
+ return [codedWidth, codedHeight];
27
+ }
28
+ const { width, height } = source;
29
+ if (width && height) {
30
+ return [width, height];
31
+ }
32
+ throw new Error('Cannot determine dimensions of the provided image source.');
33
+ }
34
+ export function sameSize(a, b) {
35
+ return a[0] === b[0] && a[1] === b[1];
36
+ }
37
+ export function resolveImageWrite(texture, source, options, layer = options.origin?.[2] ?? 0) {
38
+ const [x = 0, y = 0] = options.origin ?? [];
39
+ const [sourceX = 0, sourceY = 0] = options.sourceOrigin ?? [];
40
+ const [imageWidth, imageHeight] = imageSize(source);
41
+ const [sourceWidth = imageWidth - sourceX, sourceHeight = imageHeight - sourceY] = options.sourceSize ?? [];
42
+ let sourceSize = [sourceWidth, sourceHeight];
43
+ let size = writeRegionSize(texture, options);
44
+ if (options.fit === 'clip') {
45
+ sourceSize = size = [Math.min(sourceSize[0], size[0]), Math.min(sourceSize[1], size[1])];
46
+ }
47
+ else if (options.fit !== 'stretch' && !sameSize(sourceSize, size)) {
48
+ throw new Error(`Texture write source size ${sourceSize.join('x')} does not match target size ${size.join('x')}. Pass fit: 'stretch' to scale the source or fit: 'clip' to copy the overlapping region.`);
49
+ }
50
+ return {
51
+ source,
52
+ sourceOrigin: { x: sourceX, y: sourceY },
53
+ sourceSize,
54
+ origin: { x, y, z: layer },
55
+ size,
56
+ mipLevel: options.mipLevel ?? 0,
57
+ options,
58
+ };
59
+ }
package/data/dataIO.d.ts CHANGED
@@ -5,9 +5,9 @@ import { type BaseData } from './wgslTypes.ts';
5
5
  import type { BufferWriteOptions } from '../core/buffer/buffer.ts';
6
6
  export declare function writeData<TData extends wgsl.BaseData>(output: ISerialOutput, schema: TData, value: Infer<TData>): void;
7
7
  export declare function readData<TData extends wgsl.BaseData>(input: ISerialInput, schema: TData): Infer<TData>;
8
- export declare function calculateOffsets<T extends BaseData>(options: BufferWriteOptions | undefined, schema: T, data: InferInput<T> | ArrayBuffer): {
8
+ export declare function calculateOffsets<T extends BaseData>(options: BufferWriteOptions | undefined, schema: T, data: InferInput<T> | ArrayBuffer | ArrayBufferView): {
9
9
  startOffset: number;
10
10
  endOffset: number;
11
11
  };
12
- export declare function writeToArrayBuffer<T extends BaseData>(buffer: ArrayBuffer, schema: T, data: InferInput<T> | ArrayBuffer, options?: BufferWriteOptions): void;
12
+ export declare function writeToArrayBuffer<T extends BaseData>(buffer: ArrayBuffer, schema: T, data: InferInput<T> | ArrayBuffer | ArrayBufferView, options?: BufferWriteOptions): void;
13
13
  export declare function readFromArrayBuffer<T extends BaseData>(buffer: ArrayBuffer, schema: T): Infer<T>;
@@ -1,6 +1,7 @@
1
1
  import { type AnyBooleanVecInstance, type AnyMatInstance, type AnyVec2Instance, type AnyVec3Instance, type AnyVec4Instance, type AnyVecInstance, type v2b, type v3b, type v4b } from './wgslTypes.ts';
2
2
  type Vec = AnyVecInstance;
3
3
  type Mat = AnyMatInstance;
4
+ type Kind = 'number' | 'boolean' | Vec['kind'] | Mat['kind'];
4
5
  type Algebraic = number | boolean | Vec | Mat;
5
6
  export type ToBool<T extends Algebraic> = T extends number | boolean ? boolean : T extends AnyVec2Instance ? v2b : T extends AnyVec3Instance ? v3b : T extends AnyVec4Instance ? v4b : never;
6
7
  /**
@@ -15,11 +16,26 @@ export declare function generalizeFn<T extends Algebraic>(fn: (a: number, b: num
15
16
  /**
16
17
  * Analogous to `generalizeFn`, but the return type is a boolean vector instead.
17
18
  */
19
+ export declare function generalizeBoolFn<T extends boolean | AnyBooleanVecInstance>(fn: (a: boolean) => boolean, args: [T]): T;
18
20
  export declare function generalizeBoolFn<T extends Algebraic>(fn: (a: number, b: number) => boolean, args: [T, T]): ToBool<T>;
19
21
  export declare function generalizeBoolFn<T extends boolean | AnyBooleanVecInstance>(fn: (a: boolean, b: boolean) => boolean, args: [T, T]): ToBool<T>;
22
+ export declare function kindOf(v: Algebraic): Kind;
23
+ export declare const u32Kind: Set<Kind>;
24
+ export declare const f32Kind: Set<Kind>;
25
+ export declare const f16Kind: Set<Kind>;
26
+ export declare const matrixKind: Set<Kind>;
27
+ export declare const booleanKind: Set<Kind>;
28
+ export declare const floatKind: Set<Kind>;
29
+ export declare const signedKind: Set<Kind>;
30
+ export declare const numericKind: Set<Kind>;
31
+ export declare const numericOrBooleanKind: Set<Kind>;
32
+ export declare const numericOrMatrixKind: Set<Kind>;
33
+ export declare const crossKind: Set<Kind>;
34
+ export declare function assertKind(v: Algebraic | Algebraic[], valid: Set<Kind>, excludeScalar?: boolean): void;
35
+ export declare function assertEqualKinds(...values: Algebraic[]): void;
20
36
  /**
21
37
  * If one of the arguments is a vector and other is a number,
22
38
  * the number is up-cased to a vector.
23
39
  */
24
- export declare function upCast<T extends number | Vec>(args: [T, T]): [Exclude<T, number>, Exclude<T, number>];
40
+ export declare function upCast<T extends number | Vec | Mat>(args: [T, T]): [Exclude<T, number>, Exclude<T, number>];
25
41
  export {};
@@ -1,7 +1,7 @@
1
1
  import { vec2b, vec3b, vec4b, vecTypeToConstructor } from "./vector.js";
2
2
  import { mat2x2f, mat3x3f, mat4x4f } from "./matrix.js";
3
3
  import { isVecInstance, } from "./wgslTypes.js";
4
- import { invariant } from "../errors.js";
4
+ import { invariant, WgslTypeError } from "../errors.js";
5
5
  const booleanFor = {
6
6
  vec2f: vec2b,
7
7
  vec2h: vec2b,
@@ -62,7 +62,7 @@ export function generalizeFn(fn, args) {
62
62
  export function generalizeBoolFn(fn, args) {
63
63
  return applyArgs(fn, args, 'boolean');
64
64
  }
65
- function kindOf(v) {
65
+ export function kindOf(v) {
66
66
  if (typeof v === 'number') {
67
67
  return 'number';
68
68
  }
@@ -71,6 +71,43 @@ function kindOf(v) {
71
71
  }
72
72
  return v.kind;
73
73
  }
74
+ // Unless matrix is mentioned in the name, it is not included.
75
+ const i32Kind = new Set(['number', 'vec2i', 'vec3i', 'vec4i']);
76
+ export const u32Kind = new Set(['number', 'vec2u', 'vec3u', 'vec4u']);
77
+ export const f32Kind = new Set(['number', 'vec2f', 'vec3f', 'vec4f']);
78
+ export const f16Kind = new Set(['number', 'vec2h', 'vec3h', 'vec4h']);
79
+ export const matrixKind = new Set(['mat2x2f', 'mat3x3f', 'mat4x4f']);
80
+ export const booleanKind = new Set([
81
+ 'boolean',
82
+ 'vec2<bool>',
83
+ 'vec3<bool>',
84
+ 'vec4<bool>',
85
+ ]);
86
+ export const floatKind = new Set([...f32Kind, ...f16Kind]);
87
+ export const signedKind = new Set([...i32Kind, ...f32Kind, ...f16Kind]);
88
+ export const numericKind = new Set([...signedKind, ...u32Kind]);
89
+ export const numericOrBooleanKind = new Set([...numericKind, ...booleanKind]);
90
+ export const numericOrMatrixKind = new Set([...numericKind, ...matrixKind]);
91
+ export const crossKind = new Set(['vec3f', 'vec3h']);
92
+ export function assertKind(v, valid, excludeScalar = false) {
93
+ if (!isVecInstance(v) && Array.isArray(v)) {
94
+ v.forEach((item) => assertKind(item, valid, excludeScalar));
95
+ return;
96
+ }
97
+ const kind = kindOf(v);
98
+ if (!valid.has(kind)) {
99
+ throw new WgslTypeError(`Unsupported signature. Expected one of '${[...valid].join(', ')}', got '${kind}'.`);
100
+ }
101
+ if (excludeScalar && (kind === 'number' || kind === 'boolean')) {
102
+ throw new WgslTypeError(`Unsupported signature. Expected kind to not be scalar, got '${kind}'.`);
103
+ }
104
+ }
105
+ export function assertEqualKinds(...values) {
106
+ const kinds = new Set(values.map(kindOf));
107
+ if (kinds.size !== 1) {
108
+ throw new WgslTypeError(`Unsupported signature. Expected the following kinds to be equal: '${[...kinds].join(', ')}'.`);
109
+ }
110
+ }
74
111
  /**
75
112
  * If one of the arguments is a vector and other is a number,
76
113
  * the number is up-cased to a vector.
package/data/snippet.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { UnknownData } from './dataTypes.ts';
2
2
  import { type BaseData } from './wgslTypes.ts';
3
- export type Origin = 'uniform' | 'readonly' | 'mutable' | 'workgroup' | 'private' | 'handle' | 'function' | 'local-def' | 'constant-immutable-def' | 'runtime-immutable-def' | 'argument' | 'runtime' | 'constant';
3
+ export type Origin = 'uniform' | 'readonly' | 'mutable' | 'workgroup' | 'private' | 'handle' | 'immediate' | 'function' | 'local-def' | 'constant-immutable-def' | 'runtime-immutable-def' | 'argument' | 'runtime' | 'constant';
4
4
  /**
5
5
  * What happens to a snippet's origin when it's deep copied in JS, and left as is in WGSL?
6
6
  * e.g. `vec3f(vec3f(0, 1, 2))`
@@ -31,6 +31,10 @@ export declare const originToPtrParams: {
31
31
  readonly space: "uniform";
32
32
  readonly access: "read";
33
33
  };
34
+ readonly immediate: {
35
+ readonly space: "immediate";
36
+ readonly access: "read";
37
+ };
34
38
  readonly readonly: {
35
39
  readonly space: "storage";
36
40
  readonly access: "read";
package/data/snippet.js CHANGED
@@ -39,6 +39,7 @@ export function isAlias(snippet) {
39
39
  }
40
40
  export const originToPtrParams = {
41
41
  uniform: { space: 'uniform', access: 'read' },
42
+ immediate: { space: 'immediate', access: 'read' },
42
43
  readonly: { space: 'storage', access: 'read' },
43
44
  mutable: { space: 'storage', access: 'read-write' },
44
45
  workgroup: { space: 'workgroup', access: 'read-write' },
@@ -810,7 +810,7 @@ export interface WgslStruct<out TProps extends Record<string, BaseData> = Record
810
810
  }
811
811
  /** @deprecated Just use `WgslStruct` without any type parameters */
812
812
  export type AnyWgslStruct = WgslStruct;
813
- export type AddressSpace = 'uniform' | 'storage' | 'workgroup' | 'private' | 'function' | 'handle';
813
+ export type AddressSpace = 'uniform' | 'storage' | 'workgroup' | 'private' | 'function' | 'handle' | 'immediate';
814
814
  export type Access = 'read' | 'write' | 'read-write';
815
815
  export interface Ptr<TAddr extends AddressSpace = AddressSpace, TInner extends BaseData = BaseData, TAccess extends Access = Access> extends BaseData {
816
816
  readonly type: 'ptr';
package/errors.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { TgpuSlot } from './core/slot/slotTypes.ts';
3
3
  import type { TgpuVertexLayout } from './core/vertexLayout/vertexLayout.ts';
4
4
  import type { BaseData } from './data/wgslTypes.ts';
5
5
  import type { TgpuBindGroupLayout } from './tgpuBindGroupLayout.ts';
6
+ import type * as tinyest from 'tinyest';
6
7
  /**
7
8
  * Inspired by: https://github.com/alexreardon/tiny-invariant/blob/master/src/tiny-invariant.ts
8
9
  */
@@ -51,6 +52,9 @@ export declare class MissingBindGroupsError extends Error {
51
52
  export declare class MissingVertexBuffersError extends Error {
52
53
  constructor(layouts: Iterable<TgpuVertexLayout>);
53
54
  }
55
+ export declare class MissingImmediatesError extends Error {
56
+ constructor(name: string | undefined);
57
+ }
54
58
  export declare class IllegalVarAccessError extends Error {
55
59
  constructor(msg: string);
56
60
  }
@@ -60,6 +64,9 @@ export declare class IllegalBufferAccessError extends Error {
60
64
  export declare class WgslTypeError extends Error {
61
65
  constructor(msg: string);
62
66
  }
67
+ export declare class WgslForbiddenStatementError extends Error {
68
+ constructor(node: tinyest.AnyNode);
69
+ }
63
70
  export declare class SignatureNotSupportedError extends Error {
64
71
  constructor(actual: BaseData[], candidates: BaseData[]);
65
72
  }
package/errors.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { getName, hasTinyestMetadata } from "./shared/meta.js";
2
2
  import { DEV, TEST } from "./shared/env.js";
3
+ import { stringifyNode } from "./shared/tseynit.js";
3
4
  const prefix = 'Invariant failed';
4
5
  /**
5
6
  * Inspired by: https://github.com/alexreardon/tiny-invariant/blob/master/src/tiny-invariant.ts
@@ -115,6 +116,13 @@ export class MissingVertexBuffersError extends Error {
115
116
  Object.setPrototypeOf(this, MissingVertexBuffersError.prototype);
116
117
  }
117
118
  }
119
+ export class MissingImmediatesError extends Error {
120
+ constructor(name) {
121
+ super(`Missing value for immediate variable '${name ?? '<unnamed>'}'. Please provide it using pipeline.with(immediate, value), pass.setImmediates(immediate, value), or give the variable a default value`);
122
+ // Set the prototype explicitly.
123
+ Object.setPrototypeOf(this, MissingImmediatesError.prototype);
124
+ }
125
+ }
118
126
  export class IllegalVarAccessError extends Error {
119
127
  constructor(msg) {
120
128
  super(msg);
@@ -136,6 +144,13 @@ export class WgslTypeError extends Error {
136
144
  Object.setPrototypeOf(this, WgslTypeError.prototype);
137
145
  }
138
146
  }
147
+ export class WgslForbiddenStatementError extends Error {
148
+ constructor(node) {
149
+ super(`Expression statements like '${stringifyNode(node)};' are forbidden in WGSL. Remove the statement, or use the result in code (for example, assign it to a variable).`);
150
+ // Set the prototype explicitly.
151
+ Object.setPrototypeOf(this, WgslForbiddenStatementError.prototype);
152
+ }
153
+ }
139
154
  export class SignatureNotSupportedError extends Error {
140
155
  constructor(actual, candidates) {
141
156
  super(`Unsupported data types: ${actual
@@ -1,7 +1,7 @@
1
1
  export * as d from './data/index.ts';
2
2
  export * as std from './std/index.ts';
3
3
  export * as common from './common/index.ts';
4
- export { MissingBindGroupsError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, } from './errors.ts';
4
+ export { MissingBindGroupsError, MissingImmediatesError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, } from './errors.ts';
5
5
  export { isAccessor, isLazy, isMutableAccessor, isSlot } from './core/slot/slotTypes.ts';
6
6
  export { isComparisonSampler, isSampler } from './core/sampler/sampler.ts';
7
7
  export { isTexture } from './core/texture/texture.ts';
@@ -17,6 +17,7 @@ export { isComputePipeline, isPipeline, isRenderPipeline } from './core/pipeline
17
17
  export { isQuerySet } from './core/querySet/querySet.ts';
18
18
  export { isVariable } from './core/variable/tgpuVariable.ts';
19
19
  export { isVertexLayout } from './core/vertexLayout/vertexLayout.ts';
20
+ export { isImmediateVar } from './core/immediate/immediateVar.ts';
20
21
  export type {
21
22
  /** @deprecated Import from 'typegpu/~internal' instead */ ShaderGenerator, } from './tgsl/shaderGenerator.ts';
22
23
  export {
@@ -40,12 +41,14 @@ export type { TgpuBufferMutable, TgpuBufferReadonly, TgpuBufferUniform, } from '
40
41
  export type { TgpuBufferBinding, TgpuMutable, TgpuReadonly, TgpuUniform, } from './core/buffer/bufferBinding.ts';
41
42
  export type { Eventual, TgpuAccessor, TgpuLazy, TgpuMutableAccessor, TgpuSlot, } from './core/slot/slotTypes.ts';
42
43
  export type { RawCodeSnippetOrigin, TgpuRawCodeSnippet, } from './core/rawCodeSnippet/tgpuRawCodeSnippet.ts';
43
- export type { TextureWriteFit, TextureWriteOptions, TgpuTexture, TgpuTextureView, } from './core/texture/texture.ts';
44
+ export type { TgpuTexture, TgpuTextureView } from './core/texture/texture.ts';
45
+ export type { TextureBlobWriteOptions, TextureChannel, TextureCopyOptions, TextureRawWriteOptions, TextureWriteFit, TextureWriteOptions, } from './core/texture/textureWrite.ts';
44
46
  export type { TextureProps } from './core/texture/textureProps.ts';
45
47
  export type { RenderFlag, SampledFlag } from './core/texture/usageExtension.ts';
46
48
  export type { InitFromDeviceOptions, InitOptions } from './core/root/init.ts';
47
49
  export type { TgpuConst } from './core/constant/tgpuConstant.ts';
48
50
  export type { TgpuVar, VariableScope } from './core/variable/tgpuVariable.ts';
51
+ export type { TgpuImmediateVar } from './core/immediate/immediateVar.ts';
49
52
  export type { TgpuComparisonSampler, TgpuFixedComparisonSampler, TgpuFixedSampler, TgpuSampler, } from './core/sampler/sampler.ts';
50
53
  export type { TgpuQuerySet } from './core/querySet/querySet.ts';
51
54
  export type { ExtractBindGroupInputFromLayout, LayoutEntryToInput, TgpuBindGroup, TgpuBindGroupLayout, TgpuLayoutComparisonSampler, TgpuLayoutEntry, TgpuLayoutExternalTexture, TgpuLayoutSampler, TgpuLayoutStorage, TgpuLayoutTexture, TgpuLayoutUniform, } from './tgpuBindGroupLayout.ts';
@@ -2,7 +2,7 @@
2
2
  export * as d from "./data/index.js";
3
3
  export * as std from "./std/index.js";
4
4
  export * as common from "./common/index.js";
5
- export { MissingBindGroupsError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, } from "./errors.js";
5
+ export { MissingBindGroupsError, MissingImmediatesError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, } from "./errors.js";
6
6
  export { isAccessor, isLazy, isMutableAccessor, isSlot } from "./core/slot/slotTypes.js";
7
7
  export { isComparisonSampler, isSampler } from "./core/sampler/sampler.js";
8
8
  export { isTexture } from "./core/texture/texture.js";
@@ -18,6 +18,7 @@ export { isComputePipeline, isPipeline, isRenderPipeline } from "./core/pipeline
18
18
  export { isQuerySet } from "./core/querySet/querySet.js";
19
19
  export { isVariable } from "./core/variable/tgpuVariable.js";
20
20
  export { isVertexLayout } from "./core/vertexLayout/vertexLayout.js";
21
+ export { isImmediateVar } from "./core/immediate/immediateVar.js";
21
22
  export {
22
23
  /** @deprecated Import from 'typegpu/~internal' instead */ WgslGenerator, } from "./tgsl/wgslGenerator.js";
23
24
  export { readFromArrayBuffer, writeToArrayBuffer } from "./data/dataIO.js";
package/internal.d.ts CHANGED
@@ -5,7 +5,7 @@ export { UnknownData } from './data/dataTypes.ts';
5
5
  export { getName, setName } from './shared/meta.ts';
6
6
  export { WgslGenerator } from './tgsl/wgslGenerator.ts';
7
7
  export { snip, withValue, withDataType, withSideEffects } from './data/snippet.ts';
8
- export { stringifyNode } from './shared/tseynit.ts';
8
+ export { stringifyNode, stringifyObjectProperty } from './shared/tseynit.ts';
9
9
  export { dualImpl } from './core/function/dualImpl.ts';
10
10
  export { isNonTransferableResource, isTransferableResource, restoreResource, snapshotResource, } from './serial/registry.ts';
11
11
  export type { TgpuResourceSnapshot, TransferableResourceType } from './serial/registry.ts';
package/internal.js CHANGED
@@ -6,7 +6,7 @@ export { UnknownData } from "./data/dataTypes.js";
6
6
  export { getName, setName } from "./shared/meta.js";
7
7
  export { WgslGenerator } from "./tgsl/wgslGenerator.js";
8
8
  export { snip, withValue, withDataType, withSideEffects } from "./data/snippet.js";
9
- export { stringifyNode } from "./shared/tseynit.js";
9
+ export { stringifyNode, stringifyObjectProperty } from "./shared/tseynit.js";
10
10
  export { dualImpl } from "./core/function/dualImpl.js";
11
11
  export { isNonTransferableResource, isTransferableResource, restoreResource, snapshotResource, } from "./serial/registry.js";
12
12
  export { deserializeDataSchema, serializeDataSchema, } from "./serial/schema.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typegpu",
3
- "version": "0.12.4",
3
+ "version": "0.12.6",
4
4
  "description": "A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.",
5
5
  "keywords": [
6
6
  "compute",
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "tsover-runtime": "^0.0.7",
52
52
  "typed-binary": "^4.3.3",
53
- "tinyest": "~0.3.3"
53
+ "tinyest": "~0.3.4"
54
54
  },
55
55
  "engines": {
56
56
  "node": ">=12.20.0"
@@ -1,3 +1,4 @@
1
+ import type { TgpuImmediateVar } from './core/immediate/immediateVar.ts';
1
2
  import type { Namespace } from './core/resolve/namespace.ts';
2
3
  import type { Configurable, ExperimentalTgpuRoot } from './core/root/rootTypes.ts';
3
4
  import { type Eventual, type SlotValuePair, type TgpuLazy, type TgpuSlot } from './core/slot/slotTypes.ts';
@@ -84,6 +85,8 @@ export declare class ResolutionCtxImpl implements ResolutionCtx {
84
85
  readonly enableExtensions: WgslEnableExtension[] | undefined;
85
86
  expectedType: BaseData | undefined;
86
87
  constructor(opts: ResolutionCtxImplOptions);
88
+ registerImmediate(immediate: TgpuImmediateVar): void;
89
+ get usedImmediate(): TgpuImmediateVar | undefined;
87
90
  isIdentifierBanned(name: string): boolean;
88
91
  isIdentifierTaken(name: string, scope: 'global' | 'block'): boolean;
89
92
  makeUniqueIdentifier(primer: string | undefined, scope: 'global' | 'block'): string;
@@ -158,6 +161,7 @@ export interface ResolvedDeclaration {
158
161
  * @param usedBindGroupLayouts - List of used `tgpu.bindGroupLayout`s.
159
162
  * @param catchall - Automatically constructed bind group for buffer usages and buffer bindings, preceded by its index.
160
163
  * @param logResources - Buffers and information about used console.logs needed to decode the raw data.
164
+ * @param usedImmediate - The immediate variable used by the shader, if any.
161
165
  */
162
166
  export interface ResolutionResult {
163
167
  code: string;
@@ -165,6 +169,7 @@ export interface ResolutionResult {
165
169
  usedBindGroupLayouts: TgpuBindGroupLayout[];
166
170
  catchall: [number, TgpuBindGroup] | undefined;
167
171
  logResources: LogResources | undefined;
172
+ usedImmediate: TgpuImmediateVar | undefined;
168
173
  }
169
174
  export declare function resolve(item: Wgsl, options: ResolutionCtxImplOptions): ResolutionResult;
170
175
  export {};
package/resolutionCtx.js CHANGED
@@ -334,6 +334,7 @@ export class ResolutionCtxImpl {
334
334
  // --
335
335
  enableExtensions;
336
336
  expectedType;
337
+ #usedImmediate;
337
338
  /**
338
339
  * A counter used to generate unique identifiers for globally-scoped definitions in the 'random' strategy.
339
340
  */
@@ -345,6 +346,15 @@ export class ResolutionCtxImpl {
345
346
  this.gen = opts.shaderGenerator ?? new WgslGenerator();
346
347
  this.gen.initGenerator(this);
347
348
  }
349
+ registerImmediate(immediate) {
350
+ if (this.#usedImmediate !== undefined && this.#usedImmediate !== immediate) {
351
+ throw new Error(`Cannot use both immediate variables '${getName(this.#usedImmediate) ?? '<unnamed>'}' and '${getName(immediate) ?? '<unnamed>'}' in a single shader. At most one immediate variable is allowed per resolution.`);
352
+ }
353
+ this.#usedImmediate = immediate;
354
+ }
355
+ get usedImmediate() {
356
+ return this.#usedImmediate;
357
+ }
348
358
  isIdentifierBanned(name) {
349
359
  return bannedTokens.has(name);
350
360
  }
@@ -924,5 +934,6 @@ export function resolve(item, options) {
924
934
  usedBindGroupLayouts,
925
935
  catchall,
926
936
  logResources: ctx.logResources,
937
+ usedImmediate: ctx.usedImmediate,
927
938
  };
928
939
  }
@@ -2,6 +2,7 @@ import { type TgpuBuffer, type TgpuBufferSoul } from '../core/buffer/buffer.ts';
2
2
  import type { BaseData } from '../data/wgslTypes.ts';
3
3
  import { TgpuBufferBindingImpl, type TgpuBufferBindingSoul } from '../core/buffer/bufferBinding.ts';
4
4
  import { type TgpuConstSoul } from '../core/constant/tgpuConstant.ts';
5
+ import { type ImmediateData, type TgpuImmediateVarSoul } from '../core/immediate/immediateVar.ts';
5
6
  import { type TgpuComputePipelineSoul } from '../core/pipeline/computePipeline.ts';
6
7
  import { type TgpuRenderPipelineSoul } from '../core/pipeline/renderPipeline.ts';
7
8
  import type { TgpuQuerySetSoul } from '../core/querySet/querySet.ts';
@@ -17,7 +18,7 @@ import { type TgpuBindGroupLayoutSoul, type TgpuBindGroupSoul } from '../tgpuBin
17
18
  import type { TgpuSoul } from '../shared/soul.ts';
18
19
  import type { RestoreContext } from './types.ts';
19
20
  /** Every soul that can cross a device boundary, discriminated by `type` */
20
- export type TgpuResourceSoul = TgpuBufferSoul | TgpuBufferBindingSoul | TgpuTextureSoul | TgpuSamplerSoul | TgpuQuerySetSoul | TgpuBindGroupLayoutSoul | TgpuBindGroupSoul | TgpuVertexLayoutSoul | TgpuConstSoul | TgpuSlotSoul | TgpuAccessorSoul | TgpuComputePipelineSoul | TgpuRenderPipelineSoul | TgpuGuardedComputePipelineSoul | TgpuRootSoul;
21
+ export type TgpuResourceSoul = TgpuBufferSoul | TgpuBufferBindingSoul | TgpuTextureSoul | TgpuSamplerSoul | TgpuQuerySetSoul | TgpuBindGroupLayoutSoul | TgpuBindGroupSoul | TgpuVertexLayoutSoul | TgpuConstSoul | TgpuImmediateVarSoul | TgpuSlotSoul | TgpuAccessorSoul | TgpuComputePipelineSoul | TgpuRenderPipelineSoul | TgpuGuardedComputePipelineSoul | TgpuRootSoul;
21
22
  type Restorer<TSoul extends TgpuSoul> = (soul: TSoul, ctx: RestoreContext) => unknown;
22
23
  declare function restoreBufferBinding(soul: TgpuBufferBindingSoul): TgpuBufferBindingImpl<"uniform" | "mutable" | "readonly", BaseData>;
23
24
  /**
@@ -37,6 +38,7 @@ export declare const soulRestorers: {
37
38
  'bind-group': Restorer<TgpuBindGroupSoul>;
38
39
  'vertex-layout': (soul: TgpuVertexLayoutSoul) => import("../indexNamedExports.ts").TgpuVertexLayout<import("../data/wgslTypes.ts").WgslArray<AnyWgslData>> | import("../indexNamedExports.ts").TgpuVertexLayout<import("../data/dataTypes.ts").Disarray<AnyData>>;
39
40
  const: (soul: TgpuConstSoul) => import("../indexNamedExports.ts").TgpuConst<AnyData>;
41
+ 'immediate-var': (soul: TgpuImmediateVarSoul<ImmediateData>) => import("../indexNamedExports.ts").TgpuImmediateVar<ImmediateData>;
40
42
  slot: (soul: TgpuSlotSoul) => import("../indexNamedExports.ts").TgpuSlot<unknown>;
41
43
  accessor: (soul: TgpuAccessorSoul) => import("../indexNamedExports.ts").TgpuAccessor<AnyData>;
42
44
  'mutable-accessor': (soul: TgpuAccessorSoul) => TgpuMutableAccessor<AnyData>;
package/serial/restore.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { INTERNAL_applyBufferUsages, } from "../core/buffer/buffer.js";
2
2
  import { TgpuBufferBindingImpl } from "../core/buffer/bufferBinding.js";
3
3
  import { constant } from "../core/constant/tgpuConstant.js";
4
+ import { immediateVar, } from "../core/immediate/immediateVar.js";
4
5
  import { INTERNAL_restoreComputePipeline, } from "../core/pipeline/computePipeline.js";
5
6
  import { INTERNAL_restoreRenderPipeline, } from "../core/pipeline/renderPipeline.js";
6
7
  import { INTERNAL_restoreGuardedComputePipeline, INTERNAL_restoreRoot } from "../core/root/init.js";
@@ -57,6 +58,7 @@ export const soulRestorers = {
57
58
  throw new Error('TypeGPU vertex layout payload could not be reconstructed.');
58
59
  },
59
60
  const: (soul) => constant(soul.dataType, soul.value),
61
+ 'immediate-var': (soul) => immediateVar(soul.dataType, soul.defaultValue),
60
62
  slot: (soul) => slot(soul.defaultValue),
61
63
  accessor: (soul) => accessor(soul.schema, soul.defaultValue),
62
64
  'mutable-accessor': (soul) => mutableAccessor(soul.schema, soul.defaultValue),
package/shared/meta.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.12.4";
1
+ const version = "0.12.6";
2
2
  import { DEV, TEST } from "./env.js";
3
3
  import { $getNameForward, $soul, isMarkedInternal } from "./symbols.js";
4
4
  import { normalizeMetadata } from "./normalizeMetadata.js";
package/shared/symbols.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.12.4";
1
+ const version = "0.12.6";
2
2
  export const $internal = Symbol(`typegpu:${version}:$internal`);
3
3
  /** A plain record of all definitional state of a resource, surviving transfer between runtimes */
4
4
  export const $soul = Symbol(`typegpu:${version}:$soul`);
@@ -1,2 +1,3 @@
1
1
  import * as tinyest from 'tinyest';
2
2
  export declare function stringifyNode(node: tinyest.AnyNode): string;
3
+ export declare function stringifyObjectProperty([key, value, computed]: tinyest.ObjectProperty): string;
package/shared/tseynit.js CHANGED
@@ -28,16 +28,18 @@ function stringifyStatement(node, ident) {
28
28
  return base;
29
29
  }
30
30
  if (node[0] === NODE.let) {
31
+ const decl = `${ident}let ${stringifyExpression(node[1], ident)}`;
31
32
  if (node[2] !== undefined) {
32
- return `${ident}let ${node[1]} = ${stringifyExpression(node[2], ident)};`;
33
+ return `${decl} = ${stringifyExpression(node[2], ident)};`;
33
34
  }
34
- return `${ident}let ${node[1]};`;
35
+ return `${decl};`;
35
36
  }
36
37
  if (node[0] === NODE.const) {
38
+ const decl = `${ident}const ${stringifyExpression(node[1], ident)}`;
37
39
  if (node[2] !== undefined) {
38
- return `${ident}const ${node[1]} = ${stringifyExpression(node[2], ident)};`;
40
+ return `${decl} = ${stringifyExpression(node[2], ident)};`;
39
41
  }
40
- return `${ident}const ${node[1]};`;
42
+ return `${decl};`;
41
43
  }
42
44
  if (node[0] === NODE.for) {
43
45
  const init = node[1] ? stringifyStatement(node[1], '') : ';';
@@ -59,13 +61,30 @@ function stringifyStatement(node, ident) {
59
61
  }
60
62
  if (node[0] === NODE.forOf) {
61
63
  const leftKind = node[1][0] === NODE.const ? 'const' : 'let';
62
- const leftName = node[1][1];
64
+ const leftName = stringifyExpression(node[1][1], ident);
63
65
  const right = stringifyExpression(node[2], ident);
64
66
  const body = stringifyStatement(node[3], ident);
65
67
  return `${ident}for (${leftKind} ${leftName} of ${right}) ${body}`;
66
68
  }
69
+ if (node[0] === NODE.switch) {
70
+ const discriminant = stringifyExpression(node[1], ident);
71
+ const cases = node[2].map((c) => {
72
+ const test = c[0] === null ? 'default' : `case ${stringifyExpression(c[0], ident)}`;
73
+ if (c[1].length === 0) {
74
+ return `${test}:`;
75
+ }
76
+ const consequents = c[1].map((s) => stringifyStatement(s, ident + ' '));
77
+ return `${test}:\n${consequents.join('\n')}`;
78
+ });
79
+ return `${ident}switch (${discriminant}) {\n${cases.map((c) => `${ident + ' '}${c}`).join('\n')}\n${ident}}`;
80
+ }
67
81
  assertExhaustive(node);
68
82
  }
83
+ export function stringifyObjectProperty([key, value, computed]) {
84
+ const keyStr = computed ? `[${stringifyExpression(key, '')}]` : stringifyExpression(key, '');
85
+ const valueStr = stringifyExpression(value, '');
86
+ return `${keyStr}: ${valueStr}`;
87
+ }
69
88
  function stringifyExpression(node, ident) {
70
89
  if (typeof node === 'string') {
71
90
  return node;
@@ -73,6 +92,12 @@ function stringifyExpression(node, ident) {
73
92
  if (typeof node === 'boolean') {
74
93
  return `${node}`;
75
94
  }
95
+ if (node[0] === NODE.identifier) {
96
+ return node[1];
97
+ }
98
+ if (node[0] === NODE.booleanLiteral) {
99
+ return `${node[1]}`;
100
+ }
76
101
  if (node[0] === NODE.numericLiteral) {
77
102
  return node[1];
78
103
  }
@@ -104,9 +129,9 @@ function stringifyExpression(node, ident) {
104
129
  }
105
130
  if (node[0] === NODE.memberAccess) {
106
131
  if (Array.isArray(node[1]) && node[1][0] === NODE.numericLiteral) {
107
- return `(${stringifyExpression(node[1], ident)}).${node[2]}`;
132
+ return `(${stringifyExpression(node[1], ident)}).${stringifyExpression(node[2], ident)}`;
108
133
  }
109
- return `${wrapIfComplex(node[1], ident)}.${node[2]}`;
134
+ return `${wrapIfComplex(node[1], ident)}.${stringifyExpression(node[2], ident)}`;
110
135
  }
111
136
  if (node[0] === NODE.indexAccess) {
112
137
  return `${wrapIfComplex(node[1], ident)}[${stringifyExpression(node[2], ident)}]`;
@@ -118,6 +143,9 @@ function stringifyExpression(node, ident) {
118
143
  return `${wrapIfComplex(node[2], ident)}${node[1]}`;
119
144
  }
120
145
  if (node[0] === NODE.objectExpr) {
146
+ if (Array.isArray(node[1])) {
147
+ return `{ ${node[1].map(stringifyObjectProperty).join(', ')} }`;
148
+ }
121
149
  const entries = Object.entries(node[1]).map(([key, val]) => `${key}: ${stringifyExpression(val, ident)}`);
122
150
  return `{ ${entries.join(', ')} }`;
123
151
  }
@@ -135,6 +163,8 @@ function assertExhaustive(value) {
135
163
  function isExpression(node) {
136
164
  if (typeof node === 'string' ||
137
165
  typeof node === 'boolean' ||
166
+ node[0] === NODE.identifier ||
167
+ node[0] === NODE.booleanLiteral ||
138
168
  node[0] === NODE.numericLiteral ||
139
169
  node[0] === NODE.stringLiteral ||
140
170
  node[0] === NODE.arrayExpr ||
@@ -163,6 +193,8 @@ const SIMPLE_NODES = [
163
193
  NODE.arrayExpr, // [] make things not ambiguous
164
194
  NODE.stringLiteral,
165
195
  NODE.numericLiteral,
196
+ NODE.identifier,
197
+ NODE.booleanLiteral,
166
198
  ];
167
199
  /**
168
200
  * Stringifies expression, and wraps it in parentheses if they cannot be trivially omitted
@@ -39,7 +39,7 @@ export type Assume<T, U> = T extends U ? T : U;
39
39
  /**
40
40
  * Any typed array
41
41
  */
42
- export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Int32Array | Float32Array | Float64Array;
42
+ export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Int32Array | Float16Array | Float32Array | Float64Array;
43
43
  export declare function assertExhaustive(x: never, location: string): never;
44
44
  /**
45
45
  * Source: https://futurestud.io/tutorials/typescript-how-to-remove-index-signature-from-a-type
package/std/atomic.d.ts CHANGED
@@ -1,8 +1,15 @@
1
+ import { type _ref as ref } from '../data/ref.ts';
1
2
  import { type atomicI32, type atomicU32 } from '../data/wgslTypes.ts';
2
3
  type AnyAtomic = atomicI32 | atomicU32;
3
4
  export declare const workgroupBarrier: import("../types.ts").DualFn<(...args: never[]) => unknown>;
4
5
  export declare const storageBarrier: import("../types.ts").DualFn<(...args: never[]) => unknown>;
5
6
  export declare const textureBarrier: import("../types.ts").DualFn<(...args: never[]) => unknown>;
7
+ interface WorkgroupUniformLoad {
8
+ <T extends AnyAtomic>(value: T | ref<T>): number;
9
+ <T>(value: ref<T>): T;
10
+ <T>(value: T): T;
11
+ }
12
+ export declare const workgroupUniformLoad: import("../types.ts").DualFn<WorkgroupUniformLoad>;
6
13
  export declare const atomicLoad: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T) => number)>;
7
14
  export declare const atomicStore: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => void)>;
8
15
  export declare const atomicAdd: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => number)>;
@@ -12,4 +19,10 @@ export declare const atomicMin: import("../types.ts").DualFn<(<T extends AnyAtom
12
19
  export declare const atomicAnd: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => number)>;
13
20
  export declare const atomicOr: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => number)>;
14
21
  export declare const atomicXor: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => number)>;
22
+ export declare const atomicExchange: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, value: number) => number)>;
23
+ type AtomicCompareExchangeResult = {
24
+ old_value: number;
25
+ exchanged: boolean;
26
+ };
27
+ export declare const atomicCompareExchangeWeak: import("../types.ts").DualFn<(<T extends AnyAtomic>(a: T, compare: number, value: number) => AtomicCompareExchangeResult)>;
15
28
  export {};