typegpu 0.11.6 → 0.11.7

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 (68) 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/function/comptime.js +8 -3
  8. package/core/function/createCallableSchema.js +7 -5
  9. package/core/function/dualImpl.js +2 -2
  10. package/core/function/fnCore.js +7 -8
  11. package/core/function/tgpuComputeFn.js +1 -1
  12. package/core/function/tgpuFn.js +3 -2
  13. package/core/pipeline/computePipeline.js +3 -3
  14. package/core/pipeline/renderPipeline.js +3 -3
  15. package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +1 -1
  16. package/core/resolve/externals.js +1 -1
  17. package/core/resolve/tgpuResolve.d.ts +2 -2
  18. package/core/root/init.js +1 -1
  19. package/core/slot/accessor.js +1 -1
  20. package/core/texture/texture.js +8 -2
  21. package/core/variable/tgpuVariable.js +8 -6
  22. package/core/vertexLayout/vertexLayout.js +1 -1
  23. package/data/alignmentOf.js +1 -1
  24. package/data/attributes.d.ts +1 -1
  25. package/data/dataIO.js +1 -1
  26. package/data/dataTypes.d.ts +0 -1
  27. package/data/dataTypes.js +2 -12
  28. package/data/index.js +6 -23
  29. package/data/ref.js +20 -7
  30. package/data/snippet.d.ts +2 -1
  31. package/data/snippet.js +37 -10
  32. package/errors.d.ts +1 -4
  33. package/errors.js +1 -7
  34. package/index.d.ts +2 -2
  35. package/index.js +2 -2
  36. package/indexNamedExports.d.ts +1 -1
  37. package/package.js +1 -1
  38. package/package.json +5 -4
  39. package/resolutionCtx.js +9 -16
  40. package/shared/meta.d.ts +6 -15
  41. package/shared/meta.js +45 -38
  42. package/shared/normalizeMetadata.d.ts +32 -0
  43. package/shared/normalizeMetadata.js +40 -0
  44. package/std/atomic.js +1 -1
  45. package/std/boolean.js +36 -5
  46. package/std/environment.d.ts +48 -0
  47. package/std/environment.js +57 -0
  48. package/std/extensions.d.ts +2 -2
  49. package/std/extensions.js +2 -2
  50. package/std/index.d.ts +3 -2
  51. package/std/index.js +5 -2
  52. package/tgpuBindGroupLayout.js +1 -1
  53. package/tgsl/accessIndex.js +8 -14
  54. package/tgsl/accessProp.js +16 -29
  55. package/tgsl/consoleLog/serializers.js +1 -1
  56. package/tgsl/conversion.js +3 -3
  57. package/tgsl/forOfUtils.js +8 -5
  58. package/tgsl/generationHelpers.js +10 -11
  59. package/tgsl/infixDispatch.js +53 -0
  60. package/tgsl/shaderGenerator.d.ts +4 -1
  61. package/tgsl/shaderGenerator_members.d.ts +20 -2
  62. package/tgsl/shaderGenerator_members.js +5 -1
  63. package/tgsl/shellless.js +4 -4
  64. package/tgsl/wgslGenerator.d.ts +15 -11
  65. package/tgsl/wgslGenerator.js +173 -96
  66. package/types.d.ts +6 -4
  67. package/wgslExtensions.d.ts +3 -3
  68. package/wgslExtensions.js +3 -3
package/std/boolean.js CHANGED
@@ -2,8 +2,8 @@ import { isBool, isNumericSchema, isVec, isVecBool, isVecInstance } from "../dat
2
2
  import { isSnippetNumeric, snip } from "../data/snippet.js";
3
3
  import { stitch } from "../core/resolve/stitch.js";
4
4
  import { unify } from "../tgsl/conversion.js";
5
- import { bool, f32 } from "../data/numeric.js";
6
- import { vec2b, vec3b, vec4b } from "../data/vector.js";
5
+ import { bool, f16, f32, i32, u32 } from "../data/numeric.js";
6
+ import { vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u } from "../data/vector.js";
7
7
  import { dualImpl } from "../core/function/dualImpl.js";
8
8
  import { VectorOps } from "../data/vectorOps.js";
9
9
  import { sub } from "./operators.js";
@@ -271,6 +271,28 @@ function cpuSelect(f, t, cond) {
271
271
  if (typeof cond === "boolean") return cond ? t : f;
272
272
  return VectorOps.select[f.kind](f, t, cond);
273
273
  }
274
+ const validSelectBranchTypes = [
275
+ f32,
276
+ f16,
277
+ i32,
278
+ u32,
279
+ bool,
280
+ vec2f,
281
+ vec3f,
282
+ vec4f,
283
+ vec2h,
284
+ vec3h,
285
+ vec4h,
286
+ vec2i,
287
+ vec3i,
288
+ vec4i,
289
+ vec2u,
290
+ vec3u,
291
+ vec4u,
292
+ vec2b,
293
+ vec3b,
294
+ vec4b
295
+ ];
274
296
  /**
275
297
  * Returns `t` if `cond` is `true`, and `f` otherwise.
276
298
  * Component-wise if `cond` is a vector.
@@ -283,7 +305,7 @@ function cpuSelect(f, t, cond) {
283
305
  const select = dualImpl({
284
306
  name: "select",
285
307
  signature: (f, t, cond) => {
286
- const [uf, ut] = unify([f, t]) ?? [f, t];
308
+ const [uf, ut] = unify([f, t], validSelectBranchTypes) ?? [f, t];
287
309
  return {
288
310
  argTypes: [
289
311
  uf,
@@ -294,8 +316,17 @@ const select = dualImpl({
294
316
  };
295
317
  },
296
318
  normalImpl: cpuSelect,
297
- codegenImpl: (_ctx, [f, t, cond]) => stitch`select(${f}, ${t}, ${cond})`
319
+ codegenImpl: (ctx, [f, t, cond]) => {
320
+ const result = stitch`select(${f}, ${t}, ${cond})`;
321
+ if (!validSelectBranchTypes.includes(f.dataType) || !validSelectBranchTypes.includes(t.dataType)) throw new Error(`'${result}' is invalid, std.select requires both branches to be either scalars or vectors.`);
322
+ if (f.dataType !== t.dataType) {
323
+ const fStr = ctx.resolve(f.dataType);
324
+ const tStr = ctx.resolve(t.dataType);
325
+ throw new Error(`'${result}' is invalid, std.select requires both branches to be the same type, got [${fStr.value}, ${tStr.value}].`);
326
+ }
327
+ return result;
328
+ }
298
329
  });
299
330
 
300
331
  //#endregion
301
- export { all, allEq, and, any, eq, ge, gt, isCloseTo, le, lt, ne, not, or, select };
332
+ export { all, allEq, and, any, eq, ge, gt, isCloseTo, le, lt, ne, not, or, select, validSelectBranchTypes };
@@ -0,0 +1,48 @@
1
+ import { DualFn } from "../types.js";
2
+ import { TgpuComptime } from "../core/function/comptime.js";
3
+ import "../indexNamedExports.js";
4
+
5
+ //#region src/std/environment.d.ts
6
+
7
+ /**
8
+ * Returns `true` when the direct callee is being transpiled for GPU, otherwise `false`.
9
+ *
10
+ * @example
11
+ * const f = () => {
12
+ * 'use gpu';
13
+ * return isBeingTranspiled() ? 1 : 0;
14
+ * };
15
+ *
16
+ * f(); // returns 0, but resolved WGSL looks like this:
17
+ *
18
+ * fn f() -> i32 {
19
+ * return 1;
20
+ * }
21
+ *
22
+ * @note
23
+ * Inside `comptime`, `lazy` or `simulate`, it always returns `false`.
24
+ */
25
+ declare const isBeingTranspiled: DualFn<() => boolean>;
26
+ /**
27
+ * Returns `wgsl` if invoked during the resolution process; otherwise, returns `undefined`.
28
+ *
29
+ * @example
30
+ * const f = () => {
31
+ * 'use gpu';
32
+ * return getTargetShaderLanguage() === 'wgsl';
33
+ * };
34
+ *
35
+ * f(); // returns false, but resolved WGSL looks like this:
36
+ *
37
+ * fn f() -> bool {
38
+ * return true;
39
+ * }
40
+ *
41
+ * @note
42
+ * Inside `lazy`, it always returns `wgsl`.
43
+ * Inside `simulate`, it always returns `undefined`.
44
+ * Inside `comptime`, it returns `wgsl` if called during the resolution process; otherwise, `undefined`.
45
+ */
46
+ declare const getTargetShaderLanguage: TgpuComptime<() => string | undefined>;
47
+ //#endregion
48
+ export { getTargetShaderLanguage, isBeingTranspiled };
@@ -0,0 +1,57 @@
1
+ import { $gpuCallable } from "../shared/symbols.js";
2
+ import { getExecMode, getResolutionCtx } from "../execMode.js";
3
+ import { coerceToSnippet } from "../tgsl/generationHelpers.js";
4
+ import { comptime } from "../core/function/comptime.js";
5
+
6
+ //#region src/std/environment.ts
7
+ const impl = (() => false);
8
+ impl.toString = () => "isBeingTranspiled";
9
+ impl[$gpuCallable] = { call(_ctx, _args) {
10
+ return coerceToSnippet(true);
11
+ } };
12
+ /**
13
+ * Returns `true` when the direct callee is being transpiled for GPU, otherwise `false`.
14
+ *
15
+ * @example
16
+ * const f = () => {
17
+ * 'use gpu';
18
+ * return isBeingTranspiled() ? 1 : 0;
19
+ * };
20
+ *
21
+ * f(); // returns 0, but resolved WGSL looks like this:
22
+ *
23
+ * fn f() -> i32 {
24
+ * return 1;
25
+ * }
26
+ *
27
+ * @note
28
+ * Inside `comptime`, `lazy` or `simulate`, it always returns `false`.
29
+ */
30
+ const isBeingTranspiled = impl;
31
+ /**
32
+ * Returns `wgsl` if invoked during the resolution process; otherwise, returns `undefined`.
33
+ *
34
+ * @example
35
+ * const f = () => {
36
+ * 'use gpu';
37
+ * return getTargetShaderLanguage() === 'wgsl';
38
+ * };
39
+ *
40
+ * f(); // returns false, but resolved WGSL looks like this:
41
+ *
42
+ * fn f() -> bool {
43
+ * return true;
44
+ * }
45
+ *
46
+ * @note
47
+ * Inside `lazy`, it always returns `wgsl`.
48
+ * Inside `simulate`, it always returns `undefined`.
49
+ * Inside `comptime`, it returns `wgsl` if called during the resolution process; otherwise, `undefined`.
50
+ */
51
+ const getTargetShaderLanguage = comptime((() => {
52
+ if (!getResolutionCtx()) return;
53
+ return getExecMode().type !== "simulate" ? "wgsl" : void 0;
54
+ }));
55
+
56
+ //#endregion
57
+ export { getTargetShaderLanguage, isBeingTranspiled };
@@ -1,8 +1,8 @@
1
- import { WgslExtension } from "../wgslExtensions.js";
1
+ import { WgslEnableExtension } from "../wgslExtensions.js";
2
2
  import { TgpuComptime } from "../core/function/comptime.js";
3
3
  import "../indexNamedExports.js";
4
4
 
5
5
  //#region src/std/extensions.d.ts
6
- declare const extensionEnabled: TgpuComptime<(extensionName: WgslExtension) => boolean>;
6
+ declare const extensionEnabled: TgpuComptime<(extensionName: WgslEnableExtension) => boolean>;
7
7
  //#endregion
8
8
  export { extensionEnabled };
package/std/extensions.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { getResolutionCtx } from "../execMode.js";
2
2
  import { comptime } from "../core/function/comptime.js";
3
- import { wgslExtensions } from "../wgslExtensions.js";
3
+ import { wgslEnableExtensions } from "../wgslExtensions.js";
4
4
 
5
5
  //#region src/std/extensions.ts
6
6
  const extensionEnabled = comptime((extensionName) => {
7
7
  const resolutionCtx = getResolutionCtx();
8
8
  if (!resolutionCtx) throw new Error("Functions using `extensionEnabled` cannot be called directly. Either generate WGSL from them, or use tgpu['~unstable'].simulate(...)");
9
- if (typeof extensionName !== "string" || !wgslExtensions.includes(extensionName)) throw new Error(`extensionEnabled has to be called with a string literal representing a valid WGSL extension name. Got: '${extensionName}'`);
9
+ if (typeof extensionName !== "string" || !wgslEnableExtensions.includes(extensionName)) throw new Error(`extensionEnabled has to be called with a string literal representing a valid WGSL extension name. Got: '${extensionName}'`);
10
10
  return (resolutionCtx.enableExtensions ?? []).includes(extensionName);
11
11
  });
12
12
 
package/std/index.d.ts CHANGED
@@ -14,10 +14,11 @@ import { subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, sub
14
14
  import { extensionEnabled } from "./extensions.js";
15
15
  import { bitcastU32toF32, bitcastU32toI32 } from "./bitcast.js";
16
16
  import { range } from "./range.js";
17
+ import { getTargetShaderLanguage, isBeingTranspiled } from "./environment.js";
17
18
 
18
19
  //#region src/std/index.d.ts
19
20
  declare namespace index_d_exports {
20
- export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, gt, identity2, identity3, identity4, insertBits, inverseSqrt, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
21
+ export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, getTargetShaderLanguage, gt, identity2, identity3, identity4, insertBits, inverseSqrt, isBeingTranspiled, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
21
22
  }
22
23
  //#endregion
23
- export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, gt, identity2, identity3, identity4, index_d_exports, insertBits, inverseSqrt, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
24
+ export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, getTargetShaderLanguage, gt, identity2, identity3, identity4, index_d_exports, insertBits, inverseSqrt, isBeingTranspiled, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
package/std/index.js CHANGED
@@ -4,9 +4,9 @@ import { add, bitShiftLeft, bitShiftRight, div, mod, mul, neg, sub } from "./ope
4
4
  import { abs, acos, acosh, asin, asinh, atan, atan2, atanh, ceil, clamp, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, distance, dot, dot4I8Packed, dot4U8Packed, exp, exp2, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, insertBits, inverseSqrt, ldexp, length, log, log2, max, min, mix, modf, normalize, pow, quantizeToF16, radians, reflect, refract, reverseBits, round, saturate, sign, sin, sinh, smoothstep, sqrt, step, tan, tanh, transpose, trunc } from "./numeric.js";
5
5
  import { arrayLength } from "./array.js";
6
6
  import { range } from "./range.js";
7
+ import { all, allEq, and, any, eq, ge, gt, isCloseTo, le, lt, ne, not, or, select } from "./boolean.js";
7
8
  import { bitcastU32toF32, bitcastU32toI32 } from "./bitcast.js";
8
9
  import { pack2x16float, pack4x8unorm, unpack2x16float, unpack4x8unorm } from "./packing.js";
9
- import { all, allEq, and, any, eq, ge, gt, isCloseTo, le, lt, ne, not, or, select } from "./boolean.js";
10
10
  import { copy } from "./copy.js";
11
11
  import { discard } from "./discard.js";
12
12
  import { rotateX4, rotateY4, rotateZ4, scale4, translate4 } from "./matrix.js";
@@ -15,6 +15,7 @@ import { dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, fwidth, fwidthC
15
15
  import { textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore } from "./texture.js";
16
16
  import { subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor } from "./subgroup.js";
17
17
  import { extensionEnabled } from "./extensions.js";
18
+ import { getTargetShaderLanguage, isBeingTranspiled } from "./environment.js";
18
19
 
19
20
  //#region src/std/index.ts
20
21
  var std_exports = /* @__PURE__ */ __export({
@@ -84,12 +85,14 @@ var std_exports = /* @__PURE__ */ __export({
84
85
  fwidthCoarse: () => fwidthCoarse,
85
86
  fwidthFine: () => fwidthFine,
86
87
  ge: () => ge,
88
+ getTargetShaderLanguage: () => getTargetShaderLanguage,
87
89
  gt: () => gt,
88
90
  identity2: () => identity2,
89
91
  identity3: () => identity3,
90
92
  identity4: () => identity4,
91
93
  insertBits: () => insertBits,
92
94
  inverseSqrt: () => inverseSqrt,
95
+ isBeingTranspiled: () => isBeingTranspiled,
93
96
  isCloseTo: () => isCloseTo,
94
97
  ldexp: () => ldexp,
95
98
  le: () => le,
@@ -181,4 +184,4 @@ var std_exports = /* @__PURE__ */ __export({
181
184
  });
182
185
 
183
186
  //#endregion
184
- export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, gt, identity2, identity3, identity4, insertBits, inverseSqrt, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, std_exports, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
187
+ export { abs, acos, acosh, add, all, allEq, and, any, arrayLength, asin, asinh, atan, atan2, atanh, atomicAdd, atomicAnd, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, bitShiftLeft, bitShiftRight, bitcastU32toF32, bitcastU32toI32, ceil, clamp, copy, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, degrees, determinant, discard, distance, div, dot, dot4I8Packed, dot4U8Packed, dpdx, dpdxCoarse, dpdxFine, dpdy, dpdyCoarse, dpdyFine, eq, exp, exp2, extensionEnabled, extractBits, faceForward, firstLeadingBit, firstTrailingBit, floor, fma, fract, frexp, fwidth, fwidthCoarse, fwidthFine, ge, getTargetShaderLanguage, gt, identity2, identity3, identity4, insertBits, inverseSqrt, isBeingTranspiled, isCloseTo, ldexp, le, length, log, log2, lt, max, min, mix, mod, modf, mul, ne, neg, normalize, not, or, pack2x16float, pack4x8unorm, pow, quantizeToF16, radians, range, reflect, refract, reverseBits, rotateX4, rotateY4, rotateZ4, rotationX4, rotationY4, rotationZ4, round, saturate, scale4, scaling4, select, sign, sin, sinh, smoothstep, sqrt, std_exports, step, storageBarrier, sub, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupXor, tan, tanh, textureBarrier, textureDimensions, textureGather, textureLoad, textureSample, textureSampleBaseClampToEdge, textureSampleBias, textureSampleCompare, textureSampleCompareLevel, textureSampleGrad, textureSampleLevel, textureStore, translate4, translation4, transpose, trunc, unpack2x16float, unpack4x8unorm, workgroupBarrier };
@@ -1,7 +1,7 @@
1
1
  import { $gpuValueOf, $internal } from "./shared/symbols.js";
2
+ import { safeStringify } from "./shared/stringify.js";
2
3
  import { getName, setName } from "./shared/meta.js";
3
4
  import { NotUniformError } from "./errors.js";
4
- import { safeStringify } from "./shared/stringify.js";
5
5
  import { f32, i32, u32 } from "./data/numeric.js";
6
6
  import { NotStorageError, isUsableAsStorage } from "./extension.js";
7
7
  import { TgpuLaidOutBufferImpl, isUsableAsUniform } from "./core/buffer/bufferUsage.js";
@@ -1,6 +1,6 @@
1
- import { isNaturallyEphemeral, isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
1
+ import { isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
2
2
  import { MatrixColumnsAccess, isDisarray } from "../data/dataTypes.js";
3
- import { isEphemeralSnippet, snip } from "../data/snippet.js";
3
+ import { snip } from "../data/snippet.js";
4
4
  import { isKnownAtComptime } from "../types.js";
5
5
  import { stitch } from "../core/resolve/stitch.js";
6
6
  import { derefSnippet } from "../data/ref.js";
@@ -18,24 +18,18 @@ function accessIndex(target, indexArg) {
18
18
  const index = typeof indexArg === "number" ? coerceToSnippet(indexArg) : indexArg;
19
19
  if (isWgslArray(target.dataType) || isDisarray(target.dataType)) {
20
20
  const elementType = target.dataType.elementType;
21
- const isElementNatEph = isNaturallyEphemeral(elementType);
22
- const isTargetEphemeral = isEphemeralSnippet(target);
23
- const isIndexConstant = index.origin === "constant";
24
21
  let origin;
25
- if (target.origin === "constant-tgpu-const-ref") if (isIndexConstant) origin = isElementNatEph ? "constant" : "constant-tgpu-const-ref";
26
- else origin = isElementNatEph ? "runtime" : "runtime-tgpu-const-ref";
27
- else if (target.origin === "runtime-tgpu-const-ref") origin = isElementNatEph ? "runtime" : "runtime-tgpu-const-ref";
28
- else if (!isTargetEphemeral && !isElementNatEph) origin = target.origin;
29
- else if (isIndexConstant && target.origin === "constant") origin = "constant";
30
- else origin = "runtime";
22
+ if (target.origin === "constant-immutable-def") origin = index.origin === "constant" || index.origin === "constant-immutable-def" ? "constant-immutable-def" : "runtime-immutable-def";
23
+ else if (target.origin === "constant") origin = index.origin === "constant" || index.origin === "constant-immutable-def" ? "constant" : "runtime";
24
+ else origin = target.origin;
31
25
  if (target.value instanceof ArrayExpression && isKnownAtComptime(index)) return target.value.elements[index.value];
32
- return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, elementType, origin);
26
+ return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, elementType, origin, target.possibleSideEffects || index.possibleSideEffects);
33
27
  }
34
- if (isVec(target.dataType)) return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, target.dataType.primitive, target.origin === "constant" || target.origin === "constant-tgpu-const-ref" ? "constant" : "runtime");
28
+ if (isVec(target.dataType)) return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, target.dataType.primitive, target.origin, target.possibleSideEffects || index.possibleSideEffects);
35
29
  if (isPtr(target.dataType)) return accessIndex(derefSnippet(target), index);
36
30
  if (target.value instanceof MatrixColumnsAccess) {
37
31
  const propType = indexableTypeToResult[target.value.matrix.dataType.type];
38
- return snip(stitch`${target.value.matrix}[${index}]`, propType, target.origin);
32
+ return snip(stitch`${target.value.matrix}[${index}]`, propType, target.origin, target.possibleSideEffects || index.possibleSideEffects);
39
33
  }
40
34
  if (target.dataType.type in indexableTypeToResult) throw new Error("The only way of accessing matrix elements in TypeGPU functions is through the 'columns' property.");
41
35
  if (isKnownAtComptime(target) && isKnownAtComptime(index)) return coerceToSnippet(target.value[index.value]);
@@ -1,16 +1,15 @@
1
- import { $gpuCallable } from "../shared/symbols.js";
2
- import { isMat, isNaturallyEphemeral, isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
3
- import { InfixDispatch, MatrixColumnsAccess, UnknownData, isUnstruct, undecorate } from "../data/dataTypes.js";
4
- import { isEphemeralSnippet, isSnippet, snip } from "../data/snippet.js";
1
+ import { isMat, isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
2
+ import { MatrixColumnsAccess, UnknownData, isUnstruct, undecorate } from "../data/dataTypes.js";
3
+ import { isSnippet, snip } from "../data/snippet.js";
5
4
  import { isKnownAtComptime } from "../types.js";
6
5
  import { stitch } from "../core/resolve/stitch.js";
7
6
  import { derefSnippet } from "../data/ref.js";
8
- import { abstractInt, bool, f16, f32, i32, u32 } from "../data/numeric.js";
9
- import { coerceToSnippet } from "./generationHelpers.js";
7
+ import { bool, f16, f32, i32, u32 } from "../data/numeric.js";
8
+ import { coerceToSnippet, numericLiteralToSnippet } from "./generationHelpers.js";
10
9
  import { vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u } from "../data/vector.js";
11
10
  import { AutoStruct } from "../data/autoStruct.js";
12
11
  import { EntryInputRouter } from "../core/function/entryInputRouter.js";
13
- import { add, bitShiftLeft, bitShiftRight, div, mod, mul, sub } from "../std/operators.js";
12
+ import { InfixDispatch, infixOperators } from "./infixDispatch.js";
14
13
 
15
14
  //#region src/tgsl/accessProp.ts
16
15
  const infixKinds = [
@@ -30,15 +29,6 @@ const infixKinds = [
30
29
  "mat3x3f",
31
30
  "mat4x4f"
32
31
  ];
33
- const infixOperators = {
34
- add,
35
- sub,
36
- mul,
37
- div,
38
- mod,
39
- bitShiftLeft,
40
- bitShiftRight
41
- };
42
32
  const swizzleLenToType = {
43
33
  f: {
44
34
  1: f32,
@@ -74,23 +64,23 @@ const swizzleLenToType = {
74
64
  function accessProp(target, propName) {
75
65
  if (infixKinds.includes(target.dataType.type) && propName in infixOperators) {
76
66
  const operator = infixOperators[propName];
77
- return snip(new InfixDispatch(propName, target, operator[$gpuCallable].call.bind(operator)), UnknownData, target.origin);
67
+ return snip(new InfixDispatch(target, operator), UnknownData, target.origin, target.possibleSideEffects);
78
68
  }
79
69
  if (isWgslArray(target.dataType) && propName === "length") {
80
- if (target.dataType.elementCount === 0) return snip(stitch`arrayLength(&${target})`, u32, "runtime");
81
- return snip(target.dataType.elementCount, abstractInt, "constant");
70
+ if (target.dataType.elementCount === 0) return snip(stitch`arrayLength(&${target})`, u32, "runtime", target.possibleSideEffects);
71
+ return numericLiteralToSnippet(target.dataType.elementCount);
82
72
  }
83
- if (isMat(target.dataType) && propName === "columns") return snip(new MatrixColumnsAccess(target), UnknownData, target.origin);
73
+ if (isMat(target.dataType) && propName === "columns") return snip(new MatrixColumnsAccess(target), UnknownData, target.origin, target.possibleSideEffects);
84
74
  if (isWgslStruct(target.dataType) || isUnstruct(target.dataType)) {
85
75
  let propType = target.dataType.propTypes[propName];
86
76
  if (!propType) return;
87
77
  propType = undecorate(propType);
88
- return snip(stitch`${target}.${propName}`, propType, target.origin === "argument" ? "argument" : !isEphemeralSnippet(target) && !isNaturallyEphemeral(propType) ? target.origin : target.origin === "constant" || target.origin === "constant-tgpu-const-ref" ? "constant" : "runtime");
78
+ return snip(stitch`${target}.${propName}`, propType, target.origin, target.possibleSideEffects);
89
79
  }
90
80
  if (target.dataType instanceof AutoStruct) {
91
81
  const result = target.dataType.accessProp(propName);
92
82
  if (!result) return;
93
- return snip(stitch`${target}.${result.prop}`, result.type, "argument");
83
+ return snip(stitch`${target}.${result.prop}`, result.type, "argument", target.possibleSideEffects);
94
84
  }
95
85
  if (target.dataType instanceof EntryInputRouter) {
96
86
  const result = target.dataType.accessProp(propName);
@@ -104,19 +94,16 @@ function accessProp(target, propName) {
104
94
  return accessProp(derefed, propName);
105
95
  }
106
96
  if (isVec(target.dataType)) {
107
- if (propName === "kind") return snip(target.dataType.type, UnknownData, "constant");
97
+ if (propName === "kind") return snip(target.dataType.type, UnknownData, "constant", false);
108
98
  }
109
99
  const propLength = propName.length;
110
- if (isVec(target.dataType) && propLength >= 1 && propLength <= 4) {
111
- const isXYZW = /^[xyzw]+$/.test(propName);
112
- const isRGBA = /^[rgba]+$/.test(propName);
113
- if (!isXYZW && !isRGBA) return;
100
+ if (isVec(target.dataType) && propLength >= 1 && propLength <= 4 && /^[xyzw]+$|^[rgba]+$/.test(propName)) {
114
101
  const swizzleType = swizzleLenToType[target.dataType.type.includes("bool") ? "b" : target.dataType.type[4]][propLength];
115
102
  if (!swizzleType) return;
116
- return snip(isKnownAtComptime(target) ? target.value[propName] : stitch`${target}.${propName}`, swizzleType, target.origin === "argument" && propLength === 1 ? "argument" : target.origin === "constant" || target.origin === "constant-tgpu-const-ref" ? "constant" : "runtime");
103
+ return snip(isKnownAtComptime(target) ? target.value[propName] : stitch`${target}.${propName}`, swizzleType, propLength === 1 ? target.origin : target.origin === "constant" || target.origin === "constant-immutable-def" ? "constant" : "runtime", target.possibleSideEffects);
117
104
  }
118
105
  if (isKnownAtComptime(target) || target.dataType === UnknownData) return coerceToSnippet(target.value[propName]);
119
106
  }
120
107
 
121
108
  //#endregion
122
- export { accessProp, infixOperators };
109
+ export { accessProp };
@@ -1,5 +1,5 @@
1
- import { getName } from "../../shared/meta.js";
2
1
  import { isWgslArray, isWgslStruct } from "../../data/wgslTypes.js";
2
+ import { getName } from "../../shared/meta.js";
3
3
  import { bool, f16, f32, i32, u32 } from "../../data/numeric.js";
4
4
  import { vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u } from "../../data/vector.js";
5
5
  import { sizeOf } from "../../data/sizeOf.js";
@@ -1,12 +1,12 @@
1
1
  import { DEV, TEST } from "../shared/env.js";
2
2
  import { isMat, isPtr, isVec } from "../data/wgslTypes.js";
3
+ import { safeStringify } from "../shared/stringify.js";
3
4
  import { UnknownData, undecorate } from "../data/dataTypes.js";
4
- import { snip } from "../data/snippet.js";
5
+ import { snip, withDataType } from "../data/snippet.js";
5
6
  import { WgslTypeError, invariant } from "../errors.js";
6
7
  import { stitch } from "../core/resolve/stitch.js";
7
8
  import { RefOperator, derefSnippet } from "../data/ref.js";
8
9
  import { schemaCallWrapperGPU } from "../data/schemaCallWrapper.js";
9
- import { safeStringify } from "../shared/stringify.js";
10
10
  import { assertExhaustive } from "../shared/utilityTypes.js";
11
11
 
12
12
  //#region src/tgsl/conversion.ts
@@ -160,7 +160,7 @@ function getBestConversion(types, targetTypes) {
160
160
  function applyActionToSnippet(ctx, snippet, action, targetType) {
161
161
  if (action.action === "none") {
162
162
  if (targetType === snippet.dataType) return snippet;
163
- return snip(snippet.value, targetType, snippet.origin);
163
+ return withDataType(targetType, snippet);
164
164
  }
165
165
  switch (action.action) {
166
166
  case "ref": return snip(new RefOperator(snippet, targetType), targetType, snippet.origin);
@@ -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 };