typegpu 0.11.6 → 0.11.8

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 (72) hide show
  1. package/bin.mjs +57 -0
  2. package/builtin.d.ts +5 -1
  3. package/builtin.js +2 -0
  4. package/core/buffer/buffer.js +1 -1
  5. package/core/buffer/bufferUsage.js +18 -14
  6. package/core/constant/tgpuConstant.js +6 -6
  7. package/core/declare/tgpuDeclare.js +2 -2
  8. package/core/function/comptime.js +8 -3
  9. package/core/function/createCallableSchema.js +7 -5
  10. package/core/function/dualImpl.js +2 -2
  11. package/core/function/fnCore.js +12 -13
  12. package/core/function/tgpuComputeFn.js +1 -1
  13. package/core/function/tgpuFn.js +3 -2
  14. package/core/pipeline/computePipeline.js +3 -3
  15. package/core/pipeline/renderPipeline.js +3 -3
  16. package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +1 -1
  17. package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +2 -2
  18. package/core/resolve/externals.d.ts +1 -1
  19. package/core/resolve/externals.js +24 -10
  20. package/core/resolve/tgpuResolve.d.ts +2 -2
  21. package/core/resolve/tgpuResolve.js +2 -2
  22. package/core/root/init.js +1 -1
  23. package/core/slot/accessor.js +1 -1
  24. package/core/texture/texture.js +8 -2
  25. package/core/variable/tgpuVariable.js +8 -6
  26. package/core/vertexLayout/vertexLayout.js +1 -1
  27. package/data/alignmentOf.js +1 -1
  28. package/data/attributes.d.ts +1 -1
  29. package/data/dataIO.js +1 -1
  30. package/data/dataTypes.d.ts +0 -1
  31. package/data/dataTypes.js +2 -12
  32. package/data/index.js +6 -23
  33. package/data/ref.js +20 -7
  34. package/data/snippet.d.ts +2 -1
  35. package/data/snippet.js +37 -10
  36. package/errors.d.ts +1 -4
  37. package/errors.js +1 -7
  38. package/index.d.ts +2 -2
  39. package/index.js +2 -2
  40. package/indexNamedExports.d.ts +1 -1
  41. package/package.js +1 -1
  42. package/package.json +5 -4
  43. package/resolutionCtx.js +9 -16
  44. package/shared/meta.d.ts +6 -15
  45. package/shared/meta.js +45 -38
  46. package/shared/normalizeMetadata.d.ts +32 -0
  47. package/shared/normalizeMetadata.js +41 -0
  48. package/std/atomic.js +1 -1
  49. package/std/boolean.js +36 -5
  50. package/std/environment.d.ts +48 -0
  51. package/std/environment.js +57 -0
  52. package/std/extensions.d.ts +2 -2
  53. package/std/extensions.js +2 -2
  54. package/std/index.d.ts +3 -2
  55. package/std/index.js +5 -2
  56. package/tgpuBindGroupLayout.js +1 -1
  57. package/tgsl/accessIndex.js +8 -14
  58. package/tgsl/accessProp.js +16 -29
  59. package/tgsl/consoleLog/serializers.js +1 -1
  60. package/tgsl/conversion.js +3 -3
  61. package/tgsl/forOfUtils.js +8 -5
  62. package/tgsl/generationHelpers.js +10 -11
  63. package/tgsl/infixDispatch.js +53 -0
  64. package/tgsl/shaderGenerator.d.ts +4 -1
  65. package/tgsl/shaderGenerator_members.d.ts +20 -2
  66. package/tgsl/shaderGenerator_members.js +5 -1
  67. package/tgsl/shellless.js +4 -4
  68. package/tgsl/wgslGenerator.d.ts +15 -11
  69. package/tgsl/wgslGenerator.js +173 -96
  70. package/types.d.ts +6 -4
  71. package/wgslExtensions.d.ts +3 -3
  72. package/wgslExtensions.js +3 -3
@@ -1,7 +1,7 @@
1
1
  import { $gpuCallable } from "../shared/symbols.js";
2
- import { isPtr, isVec, isWgslArray } from "../data/wgslTypes.js";
2
+ import { isNaturallyEphemeral, isPtr, isVec, isWgslArray } from "../data/wgslTypes.js";
3
3
  import { UnknownData } from "../data/dataTypes.js";
4
- import { isEphemeralSnippet, snip } from "../data/snippet.js";
4
+ import { isAlias, snip } from "../data/snippet.js";
5
5
  import { WgslTypeError, invariant } from "../errors.js";
6
6
  import { stitch } from "../core/resolve/stitch.js";
7
7
  import { createPtrFromOrigin, implicitFrom } from "../data/ptr.js";
@@ -13,17 +13,20 @@ import { isTgpuRange } from "../std/range.js";
13
13
 
14
14
  //#region src/tgsl/forOfUtils.ts
15
15
  function getLoopVarKind(elementSnippet) {
16
- return elementSnippet.origin === "constant-tgpu-const-ref" ? "const" : "let";
16
+ return elementSnippet.origin === "constant-immutable-def" ? "const" : "let";
17
17
  }
18
18
  function getElementSnippet(iterableSnippet, index) {
19
19
  const elementSnippet = accessIndex(iterableSnippet, index);
20
20
  if (!elementSnippet) throw new WgslTypeError("`for ... of ...` loops only support array or vector iterables");
21
21
  return elementSnippet;
22
22
  }
23
+ /**
24
+ * Determines the type of the element as accessible inside of the `for .. of` loop body
25
+ */
23
26
  function getElementType(elementSnippet, iterableSnippet) {
24
27
  let elementType = elementSnippet.dataType;
25
28
  if (elementType === UnknownData) throw new WgslTypeError(stitch`The elements in iterable ${iterableSnippet} are of unknown type`);
26
- if (isEphemeralSnippet(elementSnippet) || elementSnippet.origin === "constant-tgpu-const-ref" || elementSnippet.origin === "runtime-tgpu-const-ref") return elementType;
29
+ if (isNaturallyEphemeral(elementSnippet.dataType) || elementSnippet.origin === "runtime" || elementSnippet.origin === "constant" || elementSnippet.origin === "constant-immutable-def" || elementSnippet.origin === "runtime-immutable-def") return elementType;
27
30
  if (!isPtr(elementType)) {
28
31
  const ptrType = createPtrFromOrigin(elementSnippet.origin, concretize(elementType));
29
32
  invariant(ptrType !== void 0, `Creating pointer type from origin ${elementSnippet.origin}`);
@@ -47,7 +50,7 @@ function getRangeSnippets(ctx, iterableSnippet, unroll = false) {
47
50
  comparison: step < 0 ? ">" : "<"
48
51
  };
49
52
  }
50
- if (!unroll && isEphemeralSnippet(iterableSnippet)) throw new Error(`\`for ... of ...\` loops only support std.range or iterables stored in variables.
53
+ if (!unroll && !isAlias(iterableSnippet)) throw new Error(`\`for ... of ...\` loops only support std.range or iterables stored in variables.
51
54
  -----
52
55
  You can wrap iterable with \`tgpu.unroll(...)\`. If iterable is known at comptime, the loop will be unrolled.
53
56
  -----`);
@@ -1,21 +1,20 @@
1
1
  import { $internal, $resolve } from "../shared/symbols.js";
2
2
  import { WORKAROUND_getSchema, isMatInstance, isNaturallyEphemeral, isVecInstance } from "../data/wgslTypes.js";
3
3
  import { UnknownData } from "../data/dataTypes.js";
4
- import { isEphemeralSnippet, isSnippet, snip } from "../data/snippet.js";
4
+ import { isAlias, isSnippet, snip } from "../data/snippet.js";
5
5
  import { WgslTypeError } from "../errors.js";
6
6
  import { getOwnSnippet } from "../types.js";
7
- import { stitch } from "../core/resolve/stitch.js";
8
7
  import { isRef } from "../data/ref.js";
9
8
  import { abstractFloat, abstractInt, bool, f32, i32 } from "../data/numeric.js";
10
9
 
11
10
  //#region src/tgsl/generationHelpers.ts
12
11
  function numericLiteralToSnippet(value) {
13
- if (value >= 2 ** 63 || value < -(2 ** 63)) return snip(value, abstractFloat, "constant");
12
+ if (value >= 2 ** 63 || value < -(2 ** 63)) return snip(value, abstractFloat, "constant", false);
14
13
  if (Number.isInteger(value)) {
15
14
  if (!Number.isSafeInteger(value)) console.warn(`The integer ${value} exceeds the safe integer range and may have lost precision.`);
16
- return snip(value, abstractInt, "constant");
15
+ return snip(value, abstractInt, "constant", false);
17
16
  }
18
- return snip(value, abstractFloat, "constant");
17
+ return snip(value, abstractFloat, "constant", false);
19
18
  }
20
19
  function concretize(type) {
21
20
  if (type.type === "abstractFloat") return f32;
@@ -30,11 +29,11 @@ function coerceToSnippet(value) {
30
29
  if (isRef(value)) throw new Error("Cannot use refs (d.ref(...)) from the outer scope.");
31
30
  const ownSnippet = getOwnSnippet(value);
32
31
  if (ownSnippet) return ownSnippet;
33
- if (isVecInstance(value) || isMatInstance(value)) return snip(value, WORKAROUND_getSchema(value), "constant");
34
- if (typeof value === "string" || typeof value === "function" || typeof value === "object" || typeof value === "symbol" || typeof value === "undefined" || value === null) return snip(value, UnknownData, "constant");
32
+ if (isVecInstance(value) || isMatInstance(value)) return snip(value, WORKAROUND_getSchema(value), "constant", false);
33
+ if (typeof value === "string" || typeof value === "function" || typeof value === "object" || typeof value === "symbol" || typeof value === "undefined" || value === null) return snip(value, UnknownData, "constant", false);
35
34
  if (typeof value === "number") return numericLiteralToSnippet(value);
36
- if (typeof value === "boolean") return snip(value, bool, "constant");
37
- return snip(value, UnknownData, "constant");
35
+ if (typeof value === "boolean") return snip(value, bool, "constant", false);
36
+ return snip(value, UnknownData, "constant", false);
38
37
  }
39
38
  /**
40
39
  * Intermediate representation for WGSL array expressions.
@@ -53,12 +52,12 @@ var ArrayExpression = class {
53
52
  return "ArrayExpression";
54
53
  }
55
54
  [$resolve](ctx) {
56
- for (const elem of this.elements) if (elem.origin === "argument" && !isNaturallyEphemeral(elem.dataType) || !isEphemeralSnippet(elem)) {
55
+ for (const elem of this.elements) if (isAlias(elem) && !isNaturallyEphemeral(elem.dataType)) {
57
56
  const snippetStr = ctx.resolve(elem.value, elem.dataType).value;
58
57
  const snippetType = ctx.resolve(concretize(elem.dataType)).value;
59
58
  throw new WgslTypeError(`'${snippetStr}' reference cannot be used in an array constructor.\n-----\nTry '${snippetType}(${snippetStr})' or 'arrayOf(${snippetType}, count)([...])' to copy the value instead.\n-----`);
60
59
  }
61
- return snip(stitch`${`array<${ctx.resolve(this.type.elementType).value}, ${this.elements.length}>`}(${this.elements})`, this.type, "runtime");
60
+ return ctx.gen.typeInstantiation(this.type, this.elements);
62
61
  }
63
62
  };
64
63
 
@@ -0,0 +1,53 @@
1
+ import { inCodegenMode } from "../execMode.js";
2
+ import { add, bitShiftLeft, bitShiftRight, div, mod, mul, sub } from "../std/operators.js";
3
+
4
+ //#region src/tgsl/infixDispatch.ts
5
+ const infixOperators = {
6
+ add,
7
+ sub,
8
+ mul,
9
+ div,
10
+ mod,
11
+ bitShiftLeft,
12
+ bitShiftRight
13
+ };
14
+ /**
15
+ * InfixDispatch is only used in codegen mode.
16
+ * `lhs` may either be Numeric or Snippet.
17
+ * @example
18
+ * const external = d.vec2u(1);
19
+ * const fn = () => {
20
+ * 'use gpu';
21
+ * external.mul(2); // lhs is Numeric
22
+ * d.vec2u(1).mul(2) // lhs is a snippet
23
+ * }
24
+ */
25
+ var InfixDispatch = class {
26
+ lhs;
27
+ operator;
28
+ constructor(lhs, operator) {
29
+ this.lhs = lhs;
30
+ this.operator = operator;
31
+ }
32
+ };
33
+ function isInfixDispatch(o) {
34
+ return o instanceof InfixDispatch;
35
+ }
36
+ /**
37
+ * This function is used on vec/mat prototypes.
38
+ * This is done in runtime in order to avoid a circular dependency.
39
+ */
40
+ function assignInfixOperator(base, operator, operatorSymbol) {
41
+ const opImpl = infixOperators[operator];
42
+ Object.defineProperty(base.prototype, operatorSymbol, { value: opImpl });
43
+ function jsInfixDispatchFor(arg) {
44
+ return opImpl(this, arg);
45
+ }
46
+ Object.defineProperty(base.prototype, operator, { get() {
47
+ if (inCodegenMode()) return new InfixDispatch(this, opImpl);
48
+ return jsInfixDispatchFor;
49
+ } });
50
+ }
51
+
52
+ //#endregion
53
+ export { InfixDispatch, assignInfixOperator, infixOperators, isInfixDispatch };
@@ -1,6 +1,6 @@
1
1
  import { ResolvedSnippet, Snippet } from "../data/snippet.js";
2
2
  import { GenerationCtx } from "./generationHelpers.js";
3
- import { FunctionDefinitionOptions } from "./shaderGenerator_members.js";
3
+ import { ConstantDefinitionOptions, FunctionDefinitionOptions, VariableDefinitionOptions } from "./shaderGenerator_members.js";
4
4
  import { BaseData } from "../data/wgslTypes.js";
5
5
 
6
6
  //#region src/tgsl/shaderGenerator.d.ts
@@ -13,9 +13,12 @@ import { BaseData } from "../data/wgslTypes.js";
13
13
  */
14
14
  interface ShaderGenerator {
15
15
  initGenerator(ctx: GenerationCtx): void;
16
+ declareGlobalConst(options: ConstantDefinitionOptions): ResolvedSnippet;
17
+ declareGlobalVar(options: VariableDefinitionOptions): ResolvedSnippet;
16
18
  functionDefinition(options: FunctionDefinitionOptions): string;
17
19
  typeInstantiation(schema: BaseData, args: readonly Snippet[]): ResolvedSnippet;
18
20
  typeAnnotation(schema: BaseData): string;
21
+ numericLiteral(value: number, schema: BaseData): ResolvedSnippet;
19
22
  }
20
23
  //#endregion
21
24
  export { ShaderGenerator };
@@ -1,15 +1,33 @@
1
+ import "../shared/meta.js";
1
2
  import { Origin, Snippet } from "../data/snippet.js";
2
- import { FunctionArgument, ResolutionCtx, TgpuShaderStage } from "../types.js";
3
+ import { VariableScope } from "../core/variable/tgpuVariable.js";
4
+ import { BindableBufferUsage, FunctionArgument, ResolutionCtx, TgpuShaderStage } from "../types.js";
3
5
  import { BaseData } from "../data/wgslTypes.js";
4
6
  import { UnknownData } from "../data/dataTypes.js";
5
7
  import { Block } from "tinyest";
6
8
 
7
9
  //#region src/tgsl/shaderGenerator_members.d.ts
10
+
8
11
  interface FunctionDefinitionOptions {
9
12
  readonly functionType: 'normal' | TgpuShaderStage;
13
+ readonly name: string;
14
+ readonly workgroupSize?: readonly number[] | undefined;
10
15
  readonly args: readonly FunctionArgument[];
11
16
  readonly body: Block;
12
17
  determineReturnType(): BaseData;
13
18
  }
19
+ interface ConstantDefinitionOptions {
20
+ readonly id: string;
21
+ readonly dataType: BaseData;
22
+ readonly init: Snippet;
23
+ }
24
+ interface VariableDefinitionOptions {
25
+ readonly scope: VariableScope | BindableBufferUsage | 'handle';
26
+ readonly id: string;
27
+ readonly dataType: BaseData;
28
+ readonly init: Snippet | undefined;
29
+ readonly group?: string | undefined;
30
+ readonly binding?: number | undefined;
31
+ }
14
32
  //#endregion
15
- export { FunctionDefinitionOptions };
33
+ export { ConstantDefinitionOptions, FunctionDefinitionOptions, VariableDefinitionOptions };
@@ -1,8 +1,12 @@
1
1
  import { __export } from "../_virtual/rolldown_runtime.js";
2
+ import { getName } from "../shared/meta.js";
2
3
  import { UnknownData } from "../data/dataTypes.js";
3
4
 
4
5
  //#region src/tgsl/shaderGenerator_members.ts
5
- var shaderGenerator_members_exports = /* @__PURE__ */ __export({ UnknownData: () => UnknownData });
6
+ var shaderGenerator_members_exports = /* @__PURE__ */ __export({
7
+ UnknownData: () => UnknownData,
8
+ getName: () => getName
9
+ });
6
10
 
7
11
  //#endregion
8
12
  export { shaderGenerator_members_exports };
package/tgsl/shellless.js CHANGED
@@ -1,5 +1,5 @@
1
- import { getMetaData, getName } from "../shared/meta.js";
2
1
  import { isPtr, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
2
+ import { getFunctionMetadata, getName } from "../shared/meta.js";
3
3
  import { UnknownData } from "../data/dataTypes.js";
4
4
  import { WgslTypeError } from "../errors.js";
5
5
  import { RefOperator } from "../data/ref.js";
@@ -17,15 +17,15 @@ function shallowEqualSchemas(a, b) {
17
17
  var ShelllessRepository = class {
18
18
  cache = /* @__PURE__ */ new Map();
19
19
  get(fn, argSnippets) {
20
- const meta = getMetaData(fn);
21
- if (!meta?.ast) return void 0;
20
+ const meta = getFunctionMetadata(fn);
21
+ if (!meta) return;
22
22
  if (!argSnippets && meta.ast.params.length > 0) throw new Error(`Cannot resolve '${getName(fn)}' directly, because it expects arguments. Either call it from another function, or wrap it in a shell`);
23
23
  const argTypes = (argSnippets ?? []).map((s, index) => {
24
24
  if (s.value instanceof RefOperator) {
25
25
  if (s.dataType === UnknownData) throw new WgslTypeError(`d.ref() created with primitive types must be stored in a variable before use`);
26
26
  return s.dataType;
27
27
  }
28
- if (s.dataType === UnknownData) throw new Error(`Passed illegal value ${s.value} as the #${index} argument to ${meta.name}(...)\nShellless functions can only accept arguments representing WGSL resources: constructible WGSL types, d.refs, samplers or texture views.\nRemember, that arguments such as samplers, texture views, accessors, slots etc. should be dereferenced via '.$' first.`);
28
+ if (s.dataType === UnknownData) throw new Error(`Passed illegal value ${s.value} as the #${index} argument to ${getName(fn) ?? "<unnamed>"}(...)\nShellless functions can only accept arguments representing WGSL resources: constructible WGSL types, d.refs, samplers or texture views.\nRemember, that arguments such as samplers, texture views, accessors, slots etc. should be dereferenced via '.$' first.`);
29
29
  let type = concretize(s.dataType);
30
30
  if (isPtr(type) && type.implicit) type = type.inner;
31
31
  return type;
@@ -1,6 +1,6 @@
1
- import { Origin, ResolvedSnippet, Snippet } from "../data/snippet.js";
1
+ import { ResolvedSnippet, Snippet } from "../data/snippet.js";
2
2
  import { GenerationCtx } from "./generationHelpers.js";
3
- import { FunctionDefinitionOptions } from "./shaderGenerator_members.js";
3
+ import { ConstantDefinitionOptions, FunctionDefinitionOptions, VariableDefinitionOptions } from "./shaderGenerator_members.js";
4
4
  import { ShaderGenerator } from "./shaderGenerator.js";
5
5
  import { BaseData, StorableData } from "../data/wgslTypes.js";
6
6
  import { UnknownData } from "../data/dataTypes.js";
@@ -12,22 +12,23 @@ declare class WgslGenerator implements ShaderGenerator {
12
12
  #private;
13
13
  initGenerator(ctx: GenerationCtx): void;
14
14
  protected get ctx(): GenerationCtx;
15
- _block([_, statements]: tinyest.Block, externalMap?: ExternalMap): string;
16
- _blockStatement(block: tinyest.Block, externalMap?: ExternalMap): string;
15
+ protected _block([_, statements]: tinyest.Block, externalMap?: ExternalMap): string;
16
+ protected _blockStatement(block: tinyest.Block, externalMap?: ExternalMap): string;
17
17
  refVariable(id: string, dataType: StorableData): string;
18
- blockVariable(varType: 'var' | 'let' | 'const' | '<deferred>', id: string, dataType: BaseData | UnknownData, origin: Origin): Snippet;
19
18
  /**
20
19
  * Creates a variable declaration string.
21
20
  * `keyword` may be a placeholder filled in later.
22
21
  */
23
- protected emitVarDecl(pre: string, keyword: 'var' | 'let' | 'const' | `#VAR_${number}#`, name: string, _dataType: BaseData | UnknownData, rhsStr: string): string;
24
- _identifier(id: string): Snippet;
22
+ protected _emitVarDecl(keyword: 'var' | 'let' | 'const' | `#VAR_${number}#`, name: string, _dataType: BaseData | UnknownData, rhsStr: string): string;
23
+ protected _identifier(id: string): Snippet;
25
24
  /**
26
25
  * A wrapper for `generateExpression` that updates `ctx.expectedType`
27
26
  * and tries to convert the result when it does not match the expected type.
28
27
  */
29
- _typedExpression(expression: tinyest.Expression, expectedType: BaseData | BaseData[]): Snippet;
30
- _expression(expression: tinyest.Expression): Snippet;
28
+ protected _typedExpression(expression: tinyest.Expression, expectedType: BaseData | BaseData[]): Snippet;
29
+ protected _expression(expression: tinyest.Expression): Snippet;
30
+ declareGlobalConst(options: ConstantDefinitionOptions): ResolvedSnippet;
31
+ declareGlobalVar(options: VariableDefinitionOptions): ResolvedSnippet;
31
32
  functionDefinition(options: FunctionDefinitionOptions): string;
32
33
  /**
33
34
  * Generates a WGSL type string for the given data type, and adds necessary
@@ -36,8 +37,11 @@ declare class WgslGenerator implements ShaderGenerator {
36
37
  */
37
38
  typeAnnotation(data: BaseData): string;
38
39
  typeInstantiation(schema: BaseData, args: readonly Snippet[]): ResolvedSnippet;
39
- _return(statement: tinyest.Return): string;
40
- _statement(statement: tinyest.Statement): string;
40
+ numericLiteral(value: number, schema: BaseData): ResolvedSnippet;
41
+ protected _return(statement: tinyest.Return): string;
42
+ protected _letStatement(statement: tinyest.Let): string;
43
+ protected _constStatement(statement: tinyest.Const): string;
44
+ protected _statement(statement: tinyest.Statement): string;
41
45
  /**
42
46
  * Attempts a member access lookup to mark a variable as modified.
43
47
  * @example