typegpu 0.11.2 → 0.11.3
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.
- package/core/function/autoIO.js +2 -2
- package/core/function/entryInputRouter.js +10 -16
- package/core/function/fnCore.js +16 -12
- package/core/function/shelllessImpl.js +1 -1
- package/core/function/tgpuComputeFn.js +1 -1
- package/core/function/tgpuFn.js +1 -1
- package/core/function/tgpuFragmentFn.js +1 -1
- package/core/function/tgpuVertexFn.js +1 -1
- package/data/index.d.ts +3 -3
- package/data/numeric.js +16 -14
- package/data/snippet.d.ts +1 -6
- package/data/wgslTypes.d.ts +2 -0
- package/package.js +1 -1
- package/package.json +1 -1
- package/resolutionCtx.js +81 -84
- package/tgsl/accessIndex.js +2 -2
- package/tgsl/accessProp.js +7 -2
- package/tgsl/consoleLog/logGenerator.js +15 -8
- package/tgsl/conversion.js +15 -5
- package/tgsl/forOfUtils.js +14 -6
- package/tgsl/generationHelpers.js +1 -4
- package/tgsl/shaderGenerator.d.ts +2 -3
- package/tgsl/shaderGenerator_members.d.ts +15 -2
- package/tgsl/wgslGenerator.d.ts +3 -1
- package/tgsl/wgslGenerator.js +33 -26
- package/types.d.ts +11 -6
package/core/function/autoIO.js
CHANGED
|
@@ -37,7 +37,7 @@ var AutoFragmentFn = class {
|
|
|
37
37
|
autoOut;
|
|
38
38
|
constructor(impl, varyings, locations) {
|
|
39
39
|
if (!getName(impl)) setName(impl, "fragmentFn");
|
|
40
|
-
this.#core = createFnCore(impl, "
|
|
40
|
+
this.#core = createFnCore(impl, "fragment");
|
|
41
41
|
this.autoIn = new AutoStruct({
|
|
42
42
|
...builtinFragmentIn,
|
|
43
43
|
...varyings
|
|
@@ -64,7 +64,7 @@ var AutoVertexFn = class {
|
|
|
64
64
|
autoOut;
|
|
65
65
|
constructor(impl, attribs, locations) {
|
|
66
66
|
if (!getName(impl)) setName(impl, "vertexFn");
|
|
67
|
-
this.#core = createFnCore(impl, "
|
|
67
|
+
this.#core = createFnCore(impl, "vertex");
|
|
68
68
|
this.autoIn = new AutoStruct({
|
|
69
69
|
...builtinVertexIn,
|
|
70
70
|
...attribs
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { $internal } from "../../shared/symbols.js";
|
|
2
2
|
import { isWgslStruct } from "../../data/wgslTypes.js";
|
|
3
|
-
import { undecorate } from "../../data/dataTypes.js";
|
|
4
|
-
import { snip } from "../../data/snippet.js";
|
|
5
3
|
|
|
6
4
|
//#region src/core/function/entryInputRouter.ts
|
|
7
5
|
/**
|
|
@@ -12,28 +10,24 @@ import { snip } from "../../data/snippet.js";
|
|
|
12
10
|
var EntryInputRouter = class {
|
|
13
11
|
[$internal] = {};
|
|
14
12
|
type = "entry-input-router";
|
|
15
|
-
|
|
16
|
-
dataSchema;
|
|
13
|
+
structArg;
|
|
17
14
|
/** Maps schemaKey → { WGSL arg name, type } */
|
|
18
15
|
positionalArgsMap;
|
|
19
|
-
constructor(
|
|
20
|
-
this.
|
|
21
|
-
this.
|
|
22
|
-
this.positionalArgsMap = new Map(positionalArgs.map((a) => [a.schemaKey, {
|
|
23
|
-
argName: a.argName,
|
|
24
|
-
type: a.type
|
|
25
|
-
}]));
|
|
16
|
+
constructor(structArg, positionalArgs) {
|
|
17
|
+
this.structArg = structArg;
|
|
18
|
+
this.positionalArgsMap = new Map(positionalArgs.map((a) => [a.schemaKey, a.arg]));
|
|
26
19
|
}
|
|
27
20
|
toString() {
|
|
28
21
|
return "entry-input-router";
|
|
29
22
|
}
|
|
30
23
|
accessProp(propName) {
|
|
31
24
|
const positionalEntry = this.positionalArgsMap.get(propName);
|
|
32
|
-
if (positionalEntry) return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
if (positionalEntry) return positionalEntry();
|
|
26
|
+
const structSnippet = this.structArg?.();
|
|
27
|
+
if (structSnippet && isWgslStruct(structSnippet.dataType)) return {
|
|
28
|
+
target: structSnippet,
|
|
29
|
+
prop: propName
|
|
30
|
+
};
|
|
37
31
|
}
|
|
38
32
|
};
|
|
39
33
|
|
package/core/function/fnCore.js
CHANGED
|
@@ -9,7 +9,7 @@ import { applyExternals, replaceExternalsInWgsl } from "../resolve/externals.js"
|
|
|
9
9
|
import { extractArgs } from "./extractArgs.js";
|
|
10
10
|
|
|
11
11
|
//#region src/core/function/fnCore.ts
|
|
12
|
-
function createFnCore(implementation,
|
|
12
|
+
function createFnCore(implementation, functionType, workgroupSize) {
|
|
13
13
|
/**
|
|
14
14
|
* External application has to be deferred until resolution because
|
|
15
15
|
* some externals can reference the owner function which has not been
|
|
@@ -24,6 +24,10 @@ function createFnCore(implementation, fnAttribute = "") {
|
|
|
24
24
|
},
|
|
25
25
|
resolve(ctx, argTypes, returnType, entryInput) {
|
|
26
26
|
const externalMap = {};
|
|
27
|
+
let attributes = "";
|
|
28
|
+
if (functionType === "compute") attributes = `@compute @workgroup_size(${workgroupSize?.join(", ")}) `;
|
|
29
|
+
else if (functionType === "vertex") attributes = `@vertex `;
|
|
30
|
+
else if (functionType === "fragment") attributes = `@fragment `;
|
|
27
31
|
for (const externals of externalsToApply) applyExternals(externalMap, externals);
|
|
28
32
|
const id = ctx.getUniqueName(this);
|
|
29
33
|
if (typeof implementation === "string") {
|
|
@@ -32,8 +36,8 @@ function createFnCore(implementation, fnAttribute = "") {
|
|
|
32
36
|
if (validArgNames && Object.keys(validArgNames).length > 0) applyExternals(externalMap, { in: validArgNames });
|
|
33
37
|
const replacedImpl = replaceExternalsInWgsl(ctx, externalMap, implementation);
|
|
34
38
|
let header = "";
|
|
35
|
-
let body
|
|
36
|
-
if (
|
|
39
|
+
let body = "";
|
|
40
|
+
if (functionType !== "normal" && entryInput && validArgNames) {
|
|
37
41
|
const { dataSchema, positionalArgs } = entryInput;
|
|
38
42
|
const parts = [];
|
|
39
43
|
if (dataSchema && isArgUsedInBody("in", replacedImpl)) parts.push(`in: ${ctx.resolve(dataSchema).value}`);
|
|
@@ -42,16 +46,16 @@ function createFnCore(implementation, fnAttribute = "") {
|
|
|
42
46
|
if (argName !== "" && isArgUsedInBody(argName, replacedImpl)) parts.push(`${getAttributesString(a.type)}${argName}: ${ctx.resolve(a.type).value}`);
|
|
43
47
|
}
|
|
44
48
|
const input = `(${parts.join(", ")})`;
|
|
45
|
-
const attributes = isWgslData(returnType) ? getAttributesString(returnType) : "";
|
|
46
|
-
header = `${input}${returnType !== Void ? isWgslStruct(returnType) ? ` -> ${ctx.resolve(returnType).value} ` : ` -> ${attributes !== "" ? attributes : "@location(0)"} ${ctx.resolve(returnType).value} ` : " "}`;
|
|
47
|
-
body
|
|
49
|
+
const attributes$1 = isWgslData(returnType) ? getAttributesString(returnType) : "";
|
|
50
|
+
header = `${input}${returnType !== Void ? isWgslStruct(returnType) ? ` -> ${ctx.resolve(returnType).value} ` : ` -> ${attributes$1 !== "" ? attributes$1 : "@location(0)"} ${ctx.resolve(returnType).value} ` : " "}`;
|
|
51
|
+
body = replacedImpl;
|
|
48
52
|
} else {
|
|
49
53
|
const providedArgs = extractArgs(replacedImpl);
|
|
50
54
|
if (providedArgs.args.length !== argTypes.length) throw new Error(`WGSL implementation has ${providedArgs.args.length} arguments, while the shell has ${argTypes.length} arguments.`);
|
|
51
55
|
header = `(${providedArgs.args.map((argInfo, i) => `${argInfo.identifier}: ${checkAndReturnType(ctx, `parameter ${argInfo.identifier}`, argInfo.type, argTypes[i])}`).join(", ")})${returnType === Void ? " " : ` -> ${checkAndReturnType(ctx, "return type", providedArgs.ret?.type, returnType)} `}`;
|
|
52
|
-
body
|
|
56
|
+
body = replacedImpl.slice(providedArgs.range.end);
|
|
53
57
|
}
|
|
54
|
-
ctx.addDeclaration(`${
|
|
58
|
+
ctx.addDeclaration(`${attributes}fn ${id}${header}${body}`);
|
|
55
59
|
return snip(id, returnType, "runtime");
|
|
56
60
|
}
|
|
57
61
|
const pluginData = getMetaData(implementation);
|
|
@@ -62,9 +66,9 @@ function createFnCore(implementation, fnAttribute = "") {
|
|
|
62
66
|
const missingExternals = ast.externalNames.filter((name) => !(name in externalMap));
|
|
63
67
|
if (missingExternals.length > 0) throw new MissingLinksError(getName(this), missingExternals);
|
|
64
68
|
const maybeSecondArg = ast.params[1];
|
|
65
|
-
if (maybeSecondArg && maybeSecondArg.type === "i" &&
|
|
66
|
-
const {
|
|
67
|
-
functionType
|
|
69
|
+
if (maybeSecondArg && maybeSecondArg.type === "i" && functionType !== "normal") applyExternals(externalMap, { [maybeSecondArg.name]: undecorate(returnType) });
|
|
70
|
+
const { code, returnType: actualReturnType } = ctx.fnToWgsl({
|
|
71
|
+
functionType,
|
|
68
72
|
argTypes,
|
|
69
73
|
entryInput,
|
|
70
74
|
params: ast.params,
|
|
@@ -72,7 +76,7 @@ function createFnCore(implementation, fnAttribute = "") {
|
|
|
72
76
|
body: ast.body,
|
|
73
77
|
externalMap
|
|
74
78
|
});
|
|
75
|
-
ctx.addDeclaration(`${
|
|
79
|
+
ctx.addDeclaration(`${attributes}fn ${id}${code}`);
|
|
76
80
|
return snip(id, actualReturnType, "runtime");
|
|
77
81
|
}
|
|
78
82
|
};
|
|
@@ -4,7 +4,7 @@ import { createFnCore } from "./fnCore.js";
|
|
|
4
4
|
|
|
5
5
|
//#region src/core/function/shelllessImpl.ts
|
|
6
6
|
function createShelllessImpl(argTypes, implementation) {
|
|
7
|
-
const core = createFnCore(implementation, "");
|
|
7
|
+
const core = createFnCore(implementation, "normal");
|
|
8
8
|
return {
|
|
9
9
|
[$internal]: true,
|
|
10
10
|
[$getNameForward]: core,
|
|
@@ -31,7 +31,7 @@ function isTgpuComputeFn(value) {
|
|
|
31
31
|
return value?.shell?.entryPoint === "compute";
|
|
32
32
|
}
|
|
33
33
|
function createComputeFn(shell, workgroupSize, implementation, entryInput) {
|
|
34
|
-
const core = createFnCore(implementation,
|
|
34
|
+
const core = createFnCore(implementation, "compute", workgroupSize);
|
|
35
35
|
return {
|
|
36
36
|
shell,
|
|
37
37
|
$uses(newExternals) {
|
package/core/function/tgpuFn.js
CHANGED
|
@@ -40,7 +40,7 @@ function createFn(shell, _implementation) {
|
|
|
40
40
|
pairs = _implementation[$providing]?.pairs ?? [];
|
|
41
41
|
implementation = _implementation[$internal].inner;
|
|
42
42
|
} else implementation = _implementation;
|
|
43
|
-
const core = createFnCore(implementation, "");
|
|
43
|
+
const core = createFnCore(implementation, "normal");
|
|
44
44
|
const fnBase = {
|
|
45
45
|
shell,
|
|
46
46
|
resourceType: "function",
|
|
@@ -32,7 +32,7 @@ function isTgpuFragmentFn(value) {
|
|
|
32
32
|
return value?.shell?.entryPoint === "fragment";
|
|
33
33
|
}
|
|
34
34
|
function createFragmentFn(shell, implementation) {
|
|
35
|
-
const core = createFnCore(implementation, "
|
|
35
|
+
const core = createFnCore(implementation, "fragment");
|
|
36
36
|
const outputType = shell.returnType;
|
|
37
37
|
if (typeof implementation === "string") addReturnTypeToExternals(implementation, outputType, (externals) => core.applyExternals(externals));
|
|
38
38
|
return {
|
|
@@ -32,7 +32,7 @@ function isTgpuVertexFn(value) {
|
|
|
32
32
|
return value?.shell?.entryPoint === "vertex";
|
|
33
33
|
}
|
|
34
34
|
function createVertexFn(shell, implementation) {
|
|
35
|
-
const core = createFnCore(implementation, "
|
|
35
|
+
const core = createFnCore(implementation, "vertex");
|
|
36
36
|
const entryInput = separateAllAsPositional(shell.in ?? {});
|
|
37
37
|
return {
|
|
38
38
|
shell,
|
package/data/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { AnyAttribute, HasCustomLocation, IsBuiltin, align, interpolate, invaria
|
|
|
4
4
|
import { memoryLayoutOf } from "./offsetUtils.js";
|
|
5
5
|
import { FormatToAcceptedData, FormatToWGSLType, PackedData, TgpuVertexFormatData, float16, float16x2, float16x4, float32, float32x2, float32x3, float32x4, formatToWGSLType, isPackedData, packedFormats, sint16, sint16x2, sint16x4, sint32, sint32x2, sint32x3, sint32x4, sint8, sint8x2, sint8x4, snorm16, snorm16x2, snorm16x4, snorm8, snorm8x2, snorm8x4, uint16, uint16x2, uint16x4, uint32, uint32x2, uint32x3, uint32x4, uint8, uint8x2, uint8x4, unorm10_10_10_2, unorm16, unorm16x2, unorm16x4, unorm8, unorm8x2, unorm8x4, unorm8x4_bgra } from "./vertexFormatData.js";
|
|
6
6
|
import { _ref } from "./ref.js";
|
|
7
|
-
import { Align, AnyVecInstance, AnyWgslData, AnyWgslStruct, Atomic, BaseData, Bool, Builtin, Decorated, F16, F32, I32, Interpolate, Location, Mat2x2f, Mat3x3f, Mat4x4f, Ptr, Size, StorableData, U16, U32, Vec2b, Vec2f, Vec2h, Vec2i, Vec2u, Vec3b, Vec3f, Vec3h, Vec3i, Vec3u, Vec4b, Vec4f, Vec4h, Vec4i, Vec4u, Void, WgslArray, WgslStruct, atomicI32, atomicU32, isAlignAttrib, isAtomic, isBuiltinAttrib, isDecorated, isInterpolateAttrib, isLocationAttrib, isPtr, isSizeAttrib, isWgslArray, isWgslData, isWgslStruct, m2x2f, m3x3f, m4x4f, matBase, v2b, v2f, v2i, v2u, v3b, v3f, v3i, v3u, v4b, v4f, v4i, v4u, vecBase } from "./wgslTypes.js";
|
|
7
|
+
import { Align, AnyVecInstance, AnyWgslData, AnyWgslStruct, Atomic, BaseData, Bool, Builtin, Decorated, F16, F32, I32, Interpolate, Location, Mat2x2f, Mat3x3f, Mat4x4f, Ptr, Size, StorableData, U16, U32, Vec2b, Vec2f, Vec2h, Vec2i, Vec2u, Vec3b, Vec3f, Vec3h, Vec3i, Vec3u, Vec4b, Vec4f, Vec4h, Vec4i, Vec4u, Void, WgslArray, WgslStruct, atomicI32, atomicU32, isAlignAttrib, isAtomic, isBuiltinAttrib, isDecorated, isInterpolateAttrib, isLocationAttrib, isPtr, isSizeAttrib, isWgslArray, isWgslData, isWgslStruct, m2x2f, m3x3f, m4x4f, matBase, v2b, v2f, v2h, v2i, v2u, v3b, v3f, v3h, v3i, v3u, v4b, v4f, v4h, v4i, v4u, vecBase } from "./wgslTypes.js";
|
|
8
8
|
import { WgslExternalTexture, WgslStorageTexture, WgslStorageTexture1d, WgslStorageTexture2d, WgslStorageTexture2dArray, WgslStorageTexture3d, WgslStorageTextureProps, WgslTexture, WgslTexture1d, WgslTexture2d, WgslTexture2dArray, WgslTexture3d, WgslTextureCube, WgslTextureCubeArray, WgslTextureDepth2d, WgslTextureDepth2dArray, WgslTextureDepthCube, WgslTextureDepthCubeArray, WgslTextureDepthMultisampled2d, WgslTextureMultisampled2d, texture1d, texture2d, texture2dArray, texture3d, textureCube, textureCubeArray, textureDepth2d, textureDepth2dArray, textureDepthCube, textureDepthCubeArray, textureDepthMultisampled2d, textureExternal, textureMultisampled2d, textureStorage1d, textureStorage2d, textureStorage2dArray, textureStorage3d } from "./texture.js";
|
|
9
9
|
import { Infer, InferGPU, InferInput, InferPartial, InferPatch } from "../shared/repr.js";
|
|
10
10
|
import { AnyData, AnyLooseData, Disarray, LooseDecorated, Unstruct, isData, isDisarray, isLooseData, isLooseDecorated, isUnstruct } from "./dataTypes.js";
|
|
@@ -25,7 +25,7 @@ import { deepEqual } from "./deepEqual.js";
|
|
|
25
25
|
|
|
26
26
|
//#region src/data/index.d.ts
|
|
27
27
|
declare namespace index_d_exports {
|
|
28
|
-
export { Align, AnyAttribute, AnyBuiltin, AnyData, AnyLooseData, AnyVecInstance, AnyWgslData, AnyWgslStruct, Atomic, BaseData, BaseData as BaseWgslData, Bool, Builtin, BuiltinClipDistances, BuiltinFragDepth, BuiltinFrontFacing, BuiltinGlobalInvocationId, BuiltinInstanceIndex, BuiltinLocalInvocationId, BuiltinLocalInvocationIndex, BuiltinNumWorkgroups, BuiltinPosition, BuiltinSampleIndex, BuiltinSampleMask, BuiltinVertexIndex, BuiltinWorkgroupId, Decorated, Disarray, F16, F32, FormatToAcceptedData, FormatToWGSLType, HasCustomLocation, I32, Infer, InferGPU, InferInput, InferPartial, InferPatch, Interpolate, IsBuiltin, Location, LooseDecorated, Mat2x2f, Mat3x3f, Mat4x4f, PackedData, Ptr, Size, StorableData, TgpuVertexFormatData, U16, U32, Unstruct, Vec2b, Vec2f, Vec2h, Vec2i, Vec2u, Vec3b, Vec3f, Vec3h, Vec3i, Vec3u, Vec4b, Vec4f, Vec4h, Vec4i, Vec4u, Void, WgslArray, WgslComparisonSampler, WgslExternalTexture, WgslSampler, WgslStorageTexture, WgslStorageTexture1d, WgslStorageTexture2d, WgslStorageTexture2dArray, WgslStorageTexture3d, WgslStorageTextureProps, WgslStruct, WgslTexture, WgslTexture1d, WgslTexture2d, WgslTexture2dArray, WgslTexture3d, WgslTextureCube, WgslTextureCubeArray, WgslTextureDepth2d, WgslTextureDepth2dArray, WgslTextureDepthCube, WgslTextureDepthCubeArray, WgslTextureDepthMultisampled2d, WgslTextureMultisampled2d, align, PUBLIC_alignmentOf as alignmentOf, arrayOf, atomic, atomicI32, atomicU32, bool, builtin, comparisonSampler, deepEqual, disarrayOf, f16, f32, float16, float16x2, float16x4, float32, float32x2, float32x3, float32x4, formatToWGSLType, PUBLIC_getLongestContiguousPrefix as getLongestContiguousPrefix, i32, interpolate, invariant, isAlignAttrib, isAtomic, isBuiltin, isBuiltinAttrib, PUBLIC_isContiguous as isContiguous, isData, isDecorated, isDisarray, isInterpolateAttrib, isLocationAttrib, isLooseData, isLooseDecorated, isPackedData, isPtr, isSizeAttrib, isUnstruct, isWgslArray, isWgslData, isWgslStruct, location, m2x2f, m3x3f, m4x4f, mat2x2f, mat3x3f, mat4x4f, matBase, matToArray, memoryLayoutOf, packedFormats, ptrFn, ptrHandle, ptrPrivate, ptrStorage, ptrUniform, ptrWorkgroup, _ref as ref, sampler, sint16, sint16x2, sint16x4, sint32, sint32x2, sint32x3, sint32x4, sint8, sint8x2, sint8x4, size, PUBLIC_sizeOf as sizeOf, snorm16, snorm16x2, snorm16x4, snorm8, snorm8x2, snorm8x4, struct, texture1d, texture2d, texture2dArray, texture3d, textureCube, textureCubeArray, textureDepth2d, textureDepth2dArray, textureDepthCube, textureDepthCubeArray, textureDepthMultisampled2d, textureExternal, textureMultisampled2d, textureStorage1d, textureStorage2d, textureStorage2dArray, textureStorage3d, u16, u32, uint16, uint16x2, uint16x4, uint32, uint32x2, uint32x3, uint32x4, uint8, uint8x2, uint8x4, unorm10_10_10_2, unorm16, unorm16x2, unorm16x4, unorm8, unorm8x2, unorm8x4, unorm8x4_bgra, unstruct, v2b, v2f, v2i, v2u, v3b, v3f, v3i, v3u, v4b, v4f, v4i, v4u, vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u, vecBase };
|
|
28
|
+
export { Align, AnyAttribute, AnyBuiltin, AnyData, AnyLooseData, AnyVecInstance, AnyWgslData, AnyWgslStruct, Atomic, BaseData, BaseData as BaseWgslData, Bool, Builtin, BuiltinClipDistances, BuiltinFragDepth, BuiltinFrontFacing, BuiltinGlobalInvocationId, BuiltinInstanceIndex, BuiltinLocalInvocationId, BuiltinLocalInvocationIndex, BuiltinNumWorkgroups, BuiltinPosition, BuiltinSampleIndex, BuiltinSampleMask, BuiltinVertexIndex, BuiltinWorkgroupId, Decorated, Disarray, F16, F32, FormatToAcceptedData, FormatToWGSLType, HasCustomLocation, I32, Infer, InferGPU, InferInput, InferPartial, InferPatch, Interpolate, IsBuiltin, Location, LooseDecorated, Mat2x2f, Mat3x3f, Mat4x4f, PackedData, Ptr, Size, StorableData, TgpuVertexFormatData, U16, U32, Unstruct, Vec2b, Vec2f, Vec2h, Vec2i, Vec2u, Vec3b, Vec3f, Vec3h, Vec3i, Vec3u, Vec4b, Vec4f, Vec4h, Vec4i, Vec4u, Void, WgslArray, WgslComparisonSampler, WgslExternalTexture, WgslSampler, WgslStorageTexture, WgslStorageTexture1d, WgslStorageTexture2d, WgslStorageTexture2dArray, WgslStorageTexture3d, WgslStorageTextureProps, WgslStruct, WgslTexture, WgslTexture1d, WgslTexture2d, WgslTexture2dArray, WgslTexture3d, WgslTextureCube, WgslTextureCubeArray, WgslTextureDepth2d, WgslTextureDepth2dArray, WgslTextureDepthCube, WgslTextureDepthCubeArray, WgslTextureDepthMultisampled2d, WgslTextureMultisampled2d, align, PUBLIC_alignmentOf as alignmentOf, arrayOf, atomic, atomicI32, atomicU32, bool, builtin, comparisonSampler, deepEqual, disarrayOf, f16, f32, float16, float16x2, float16x4, float32, float32x2, float32x3, float32x4, formatToWGSLType, PUBLIC_getLongestContiguousPrefix as getLongestContiguousPrefix, i32, interpolate, invariant, isAlignAttrib, isAtomic, isBuiltin, isBuiltinAttrib, PUBLIC_isContiguous as isContiguous, isData, isDecorated, isDisarray, isInterpolateAttrib, isLocationAttrib, isLooseData, isLooseDecorated, isPackedData, isPtr, isSizeAttrib, isUnstruct, isWgslArray, isWgslData, isWgslStruct, location, m2x2f, m3x3f, m4x4f, mat2x2f, mat3x3f, mat4x4f, matBase, matToArray, memoryLayoutOf, packedFormats, ptrFn, ptrHandle, ptrPrivate, ptrStorage, ptrUniform, ptrWorkgroup, _ref as ref, sampler, sint16, sint16x2, sint16x4, sint32, sint32x2, sint32x3, sint32x4, sint8, sint8x2, sint8x4, size, PUBLIC_sizeOf as sizeOf, snorm16, snorm16x2, snorm16x4, snorm8, snorm8x2, snorm8x4, struct, texture1d, texture2d, texture2dArray, texture3d, textureCube, textureCubeArray, textureDepth2d, textureDepth2dArray, textureDepthCube, textureDepthCubeArray, textureDepthMultisampled2d, textureExternal, textureMultisampled2d, textureStorage1d, textureStorage2d, textureStorage2dArray, textureStorage3d, u16, u32, uint16, uint16x2, uint16x4, uint32, uint32x2, uint32x3, uint32x4, uint8, uint8x2, uint8x4, unorm10_10_10_2, unorm16, unorm16x2, unorm16x4, unorm8, unorm8x2, unorm8x4, unorm8x4_bgra, unstruct, v2b, v2f, v2h, v2i, v2u, v3b, v3f, v3h, v3i, v3u, v4b, v4f, v4h, v4i, v4u, vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u, vecBase };
|
|
29
29
|
}
|
|
30
30
|
//#endregion
|
|
31
|
-
export { type Align, type AnyAttribute, type AnyBuiltin, type AnyData, type AnyLooseData, type AnyVecInstance, type AnyWgslData, type AnyWgslStruct, type Atomic, type BaseData, type BaseData as BaseWgslData, type Bool, type Builtin, type BuiltinClipDistances, type BuiltinFragDepth, type BuiltinFrontFacing, type BuiltinGlobalInvocationId, type BuiltinInstanceIndex, type BuiltinLocalInvocationId, type BuiltinLocalInvocationIndex, type BuiltinNumWorkgroups, type BuiltinPosition, type BuiltinSampleIndex, type BuiltinSampleMask, type BuiltinVertexIndex, type BuiltinWorkgroupId, type Decorated, type Disarray, type F16, type F32, FormatToAcceptedData, FormatToWGSLType, type HasCustomLocation, type I32, type Infer, type InferGPU, type InferInput, type InferPartial, type InferPatch, type Interpolate, type IsBuiltin, type Location, type LooseDecorated, type Mat2x2f, type Mat3x3f, type Mat4x4f, PackedData, type Ptr, type Size, type StorableData, TgpuVertexFormatData, type U16, type U32, type Unstruct, type Vec2b, type Vec2f, type Vec2h, type Vec2i, type Vec2u, type Vec3b, type Vec3f, type Vec3h, type Vec3i, type Vec3u, type Vec4b, type Vec4f, type Vec4h, type Vec4i, type Vec4u, Void, type WgslArray, type WgslComparisonSampler, type WgslExternalTexture, type WgslSampler, type WgslStorageTexture, type WgslStorageTexture1d, type WgslStorageTexture2d, type WgslStorageTexture2dArray, type WgslStorageTexture3d, type WgslStorageTextureProps, type WgslStruct, type WgslTexture, type WgslTexture1d, type WgslTexture2d, type WgslTexture2dArray, type WgslTexture3d, type WgslTextureCube, type WgslTextureCubeArray, type WgslTextureDepth2d, type WgslTextureDepth2dArray, type WgslTextureDepthCube, type WgslTextureDepthCubeArray, type WgslTextureDepthMultisampled2d, type WgslTextureMultisampled2d, align, PUBLIC_alignmentOf as alignmentOf, arrayOf, atomic, type atomicI32, type atomicU32, bool, builtin, comparisonSampler, deepEqual, disarrayOf, f16, f32, float16, float16x2, float16x4, float32, float32x2, float32x3, float32x4, formatToWGSLType, PUBLIC_getLongestContiguousPrefix as getLongestContiguousPrefix, i32, index_d_exports, interpolate, invariant, isAlignAttrib, isAtomic, isBuiltin, isBuiltinAttrib, PUBLIC_isContiguous as isContiguous, isData, isDecorated, isDisarray, isInterpolateAttrib, isLocationAttrib, isLooseData, isLooseDecorated, isPackedData, isPtr, isSizeAttrib, isUnstruct, isWgslArray, isWgslData, isWgslStruct, location, type m2x2f, type m3x3f, type m4x4f, mat2x2f, mat3x3f, mat4x4f, type matBase, matToArray, memoryLayoutOf, packedFormats, ptrFn, ptrHandle, ptrPrivate, ptrStorage, ptrUniform, ptrWorkgroup, _ref as ref, sampler, sint16, sint16x2, sint16x4, sint32, sint32x2, sint32x3, sint32x4, sint8, sint8x2, sint8x4, size, PUBLIC_sizeOf as sizeOf, snorm16, snorm16x2, snorm16x4, snorm8, snorm8x2, snorm8x4, struct, texture1d, texture2d, texture2dArray, texture3d, textureCube, textureCubeArray, textureDepth2d, textureDepth2dArray, textureDepthCube, textureDepthCubeArray, textureDepthMultisampled2d, textureExternal, textureMultisampled2d, textureStorage1d, textureStorage2d, textureStorage2dArray, textureStorage3d, u16, u32, uint16, uint16x2, uint16x4, uint32, uint32x2, uint32x3, uint32x4, uint8, uint8x2, uint8x4, unorm10_10_10_2, unorm16, unorm16x2, unorm16x4, unorm8, unorm8x2, unorm8x4, unorm8x4_bgra, unstruct, type v2b, type v2f, type v2i, type v2u, type v3b, type v3f, type v3i, type v3u, type v4b, type v4f, type v4i, type v4u, vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u, type vecBase };
|
|
31
|
+
export { type Align, type AnyAttribute, type AnyBuiltin, type AnyData, type AnyLooseData, type AnyVecInstance, type AnyWgslData, type AnyWgslStruct, type Atomic, type BaseData, type BaseData as BaseWgslData, type Bool, type Builtin, type BuiltinClipDistances, type BuiltinFragDepth, type BuiltinFrontFacing, type BuiltinGlobalInvocationId, type BuiltinInstanceIndex, type BuiltinLocalInvocationId, type BuiltinLocalInvocationIndex, type BuiltinNumWorkgroups, type BuiltinPosition, type BuiltinSampleIndex, type BuiltinSampleMask, type BuiltinVertexIndex, type BuiltinWorkgroupId, type Decorated, type Disarray, type F16, type F32, FormatToAcceptedData, FormatToWGSLType, type HasCustomLocation, type I32, type Infer, type InferGPU, type InferInput, type InferPartial, type InferPatch, type Interpolate, type IsBuiltin, type Location, type LooseDecorated, type Mat2x2f, type Mat3x3f, type Mat4x4f, PackedData, type Ptr, type Size, type StorableData, TgpuVertexFormatData, type U16, type U32, type Unstruct, type Vec2b, type Vec2f, type Vec2h, type Vec2i, type Vec2u, type Vec3b, type Vec3f, type Vec3h, type Vec3i, type Vec3u, type Vec4b, type Vec4f, type Vec4h, type Vec4i, type Vec4u, Void, type WgslArray, type WgslComparisonSampler, type WgslExternalTexture, type WgslSampler, type WgslStorageTexture, type WgslStorageTexture1d, type WgslStorageTexture2d, type WgslStorageTexture2dArray, type WgslStorageTexture3d, type WgslStorageTextureProps, type WgslStruct, type WgslTexture, type WgslTexture1d, type WgslTexture2d, type WgslTexture2dArray, type WgslTexture3d, type WgslTextureCube, type WgslTextureCubeArray, type WgslTextureDepth2d, type WgslTextureDepth2dArray, type WgslTextureDepthCube, type WgslTextureDepthCubeArray, type WgslTextureDepthMultisampled2d, type WgslTextureMultisampled2d, align, PUBLIC_alignmentOf as alignmentOf, arrayOf, atomic, type atomicI32, type atomicU32, bool, builtin, comparisonSampler, deepEqual, disarrayOf, f16, f32, float16, float16x2, float16x4, float32, float32x2, float32x3, float32x4, formatToWGSLType, PUBLIC_getLongestContiguousPrefix as getLongestContiguousPrefix, i32, index_d_exports, interpolate, invariant, isAlignAttrib, isAtomic, isBuiltin, isBuiltinAttrib, PUBLIC_isContiguous as isContiguous, isData, isDecorated, isDisarray, isInterpolateAttrib, isLocationAttrib, isLooseData, isLooseDecorated, isPackedData, isPtr, isSizeAttrib, isUnstruct, isWgslArray, isWgslData, isWgslStruct, location, type m2x2f, type m3x3f, type m4x4f, mat2x2f, mat3x3f, mat4x4f, type matBase, matToArray, memoryLayoutOf, packedFormats, ptrFn, ptrHandle, ptrPrivate, ptrStorage, ptrUniform, ptrWorkgroup, _ref as ref, sampler, sint16, sint16x2, sint16x4, sint32, sint32x2, sint32x3, sint32x4, sint8, sint8x2, sint8x4, size, PUBLIC_sizeOf as sizeOf, snorm16, snorm16x2, snorm16x4, snorm8, snorm8x2, snorm8x4, struct, texture1d, texture2d, texture2dArray, texture3d, textureCube, textureCubeArray, textureDepth2d, textureDepth2dArray, textureDepthCube, textureDepthCubeArray, textureDepthMultisampled2d, textureExternal, textureMultisampled2d, textureStorage1d, textureStorage2d, textureStorage2dArray, textureStorage3d, u16, u32, uint16, uint16x2, uint16x4, uint32, uint32x2, uint32x3, uint32x4, uint8, uint8x2, uint8x4, unorm10_10_10_2, unorm16, unorm16x2, unorm16x4, unorm8, unorm8x2, unorm8x4, unorm8x4_bgra, unstruct, type v2b, type v2f, type v2h, type v2i, type v2u, type v3b, type v3f, type v3h, type v3i, type v3u, type v4b, type v4f, type v4h, type v4i, type v4u, vec2b, vec2f, vec2h, vec2i, vec2u, vec3b, vec3f, vec3h, vec3i, vec3u, vec4b, vec4f, vec4h, vec4i, vec4u, type vecBase };
|
package/data/numeric.js
CHANGED
|
@@ -2,20 +2,6 @@ import { $internal } from "../shared/symbols.js";
|
|
|
2
2
|
import { callableSchema } from "../core/function/createCallableSchema.js";
|
|
3
3
|
|
|
4
4
|
//#region src/data/numeric.ts
|
|
5
|
-
const abstractInt = {
|
|
6
|
-
[$internal]: {},
|
|
7
|
-
type: "abstractInt",
|
|
8
|
-
toString() {
|
|
9
|
-
return "abstractInt";
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
const abstractFloat = {
|
|
13
|
-
[$internal]: {},
|
|
14
|
-
type: "abstractFloat",
|
|
15
|
-
toString() {
|
|
16
|
-
return "abstractFloat";
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
5
|
const boolCast = callableSchema({
|
|
20
6
|
name: "bool",
|
|
21
7
|
schema: () => bool,
|
|
@@ -218,6 +204,22 @@ const f16 = Object.assign(f16Cast, {
|
|
|
218
204
|
[$internal]: {},
|
|
219
205
|
type: "f16"
|
|
220
206
|
});
|
|
207
|
+
const abstractInt = {
|
|
208
|
+
[$internal]: {},
|
|
209
|
+
type: "abstractInt",
|
|
210
|
+
toString() {
|
|
211
|
+
return "abstractInt";
|
|
212
|
+
},
|
|
213
|
+
concretized: i32
|
|
214
|
+
};
|
|
215
|
+
const abstractFloat = {
|
|
216
|
+
[$internal]: {},
|
|
217
|
+
type: "abstractFloat",
|
|
218
|
+
toString() {
|
|
219
|
+
return "abstractFloat";
|
|
220
|
+
},
|
|
221
|
+
concretized: f32
|
|
222
|
+
};
|
|
221
223
|
|
|
222
224
|
//#endregion
|
|
223
225
|
export { abstractFloat, abstractInt, bool, f16, f32, i32, u16, u32 };
|
package/data/snippet.d.ts
CHANGED
|
@@ -12,14 +12,9 @@ interface Snippet {
|
|
|
12
12
|
readonly dataType: BaseData | UnknownData;
|
|
13
13
|
readonly origin: Origin;
|
|
14
14
|
}
|
|
15
|
-
interface ResolvedSnippet {
|
|
15
|
+
interface ResolvedSnippet extends Snippet {
|
|
16
16
|
readonly value: string;
|
|
17
|
-
/**
|
|
18
|
-
* The type that `value` is assignable to (not necessary exactly inferred as).
|
|
19
|
-
* E.g. `1.1` is assignable to `f32`, but `1.1` itself is an abstract float
|
|
20
|
-
*/
|
|
21
17
|
readonly dataType: BaseData;
|
|
22
|
-
readonly origin: Origin;
|
|
23
18
|
}
|
|
24
19
|
type MapValueToSnippet<T> = { [K in keyof T]: Snippet };
|
|
25
20
|
//#endregion
|
package/data/wgslTypes.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ interface matInfixNotation<T extends matBase> {
|
|
|
72
72
|
*/
|
|
73
73
|
interface AbstractInt extends BaseData {
|
|
74
74
|
readonly type: 'abstractInt';
|
|
75
|
+
readonly concretized: I32;
|
|
75
76
|
readonly [$repr]: number;
|
|
76
77
|
readonly [$invalidSchemaReason]: 'Abstract numerics are not host-shareable';
|
|
77
78
|
}
|
|
@@ -80,6 +81,7 @@ interface AbstractInt extends BaseData {
|
|
|
80
81
|
*/
|
|
81
82
|
interface AbstractFloat extends BaseData {
|
|
82
83
|
readonly type: 'abstractFloat';
|
|
84
|
+
readonly concretized: F32;
|
|
83
85
|
readonly [$repr]: number;
|
|
84
86
|
readonly [$invalidSchemaReason]: 'Abstract numerics are not host-shareable';
|
|
85
87
|
}
|
package/package.js
CHANGED
package/package.json
CHANGED
package/resolutionCtx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $internal, $providing, $resolve, isMarkedInternal } from "./shared/symbols.js";
|
|
2
2
|
import { getName, hasTinyestMetadata, setName } from "./shared/meta.js";
|
|
3
3
|
import { Void, isPtr, isWgslArray, isWgslStruct } from "./data/wgslTypes.js";
|
|
4
|
-
import { UnknownData, isData
|
|
4
|
+
import { UnknownData, isData } from "./data/dataTypes.js";
|
|
5
5
|
import { snip } from "./data/snippet.js";
|
|
6
6
|
import { MissingSlotValueError, ResolutionError, WgslTypeError, invariant } from "./errors.js";
|
|
7
7
|
import { isLazy, isProviding, isSlot } from "./core/slot/slotTypes.js";
|
|
@@ -12,7 +12,6 @@ import { safeStringify } from "./shared/stringify.js";
|
|
|
12
12
|
import { getBestConversion } from "./tgsl/conversion.js";
|
|
13
13
|
import { bool } from "./data/numeric.js";
|
|
14
14
|
import { coerceToSnippet, concretize, numericLiteralToSnippet } from "./tgsl/generationHelpers.js";
|
|
15
|
-
import { getAttributesString } from "./data/attributes.js";
|
|
16
15
|
import { createIoSchema } from "./core/function/ioSchema.js";
|
|
17
16
|
import { AutoStruct } from "./data/autoStruct.js";
|
|
18
17
|
import { EntryInputRouter } from "./core/function/entryInputRouter.js";
|
|
@@ -64,12 +63,11 @@ var ItemStateStackImpl = class {
|
|
|
64
63
|
bindingMap: new WeakMap(pairs)
|
|
65
64
|
});
|
|
66
65
|
}
|
|
67
|
-
pushFunctionScope(functionType,
|
|
66
|
+
pushFunctionScope(functionType, argAccess, returnType, externalMap) {
|
|
68
67
|
const scope = {
|
|
69
68
|
type: "functionScope",
|
|
70
69
|
functionType,
|
|
71
|
-
|
|
72
|
-
argAliases,
|
|
70
|
+
argAccess,
|
|
73
71
|
returnType,
|
|
74
72
|
externalMap,
|
|
75
73
|
reportedReturnTypes: /* @__PURE__ */ new Set()
|
|
@@ -106,9 +104,8 @@ var ItemStateStackImpl = class {
|
|
|
106
104
|
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
107
105
|
const layer = this._stack[i];
|
|
108
106
|
if (layer?.type === "functionScope") {
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
if (layer.argAliases[id]) return layer.argAliases[id];
|
|
107
|
+
const access = layer.argAccess[id];
|
|
108
|
+
if (access) return access();
|
|
112
109
|
const external = layer.externalMap[id];
|
|
113
110
|
if (external !== void 0 && external !== null) return coerceToSnippet(external);
|
|
114
111
|
return;
|
|
@@ -189,6 +186,27 @@ var IndentController = class {
|
|
|
189
186
|
}
|
|
190
187
|
}
|
|
191
188
|
};
|
|
189
|
+
function createArgument(name, type, origin = "argument") {
|
|
190
|
+
let used = false;
|
|
191
|
+
return {
|
|
192
|
+
name,
|
|
193
|
+
access: () => {
|
|
194
|
+
used = true;
|
|
195
|
+
return snip(name, type, origin);
|
|
196
|
+
},
|
|
197
|
+
decoratedType: type,
|
|
198
|
+
get used() {
|
|
199
|
+
return used;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function createArgumentPropAccess(argAccess, prop) {
|
|
204
|
+
return () => {
|
|
205
|
+
const argSnippet = argAccess();
|
|
206
|
+
if (!argSnippet) return;
|
|
207
|
+
return accessProp(argSnippet, prop);
|
|
208
|
+
};
|
|
209
|
+
}
|
|
192
210
|
var ResolutionCtxImpl = class {
|
|
193
211
|
#namespaceInternal;
|
|
194
212
|
_indentController = new IndentController();
|
|
@@ -287,107 +305,93 @@ var ResolutionCtxImpl = class {
|
|
|
287
305
|
try {
|
|
288
306
|
this.#namespaceInternal.nameRegistry.pushFunctionScope();
|
|
289
307
|
const args = [];
|
|
290
|
-
const
|
|
291
|
-
const pendingHeaderEntries = [];
|
|
308
|
+
const argAccess = {};
|
|
292
309
|
if (options.entryInput) {
|
|
293
310
|
const { dataSchema, positionalArgs } = options.entryInput;
|
|
294
311
|
const firstParam = options.params[0];
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
if (structArg) {
|
|
298
|
-
args.push(structArg);
|
|
299
|
-
pendingHeaderEntries.push({
|
|
300
|
-
argName: structArgName,
|
|
301
|
-
header: `${structArgName}: ${this.resolve(dataSchema).value}`
|
|
302
|
-
});
|
|
303
|
-
}
|
|
312
|
+
const structArg = dataSchema ? createArgument(this.makeNameValid("_arg_0"), dataSchema) : void 0;
|
|
313
|
+
if (structArg) args.push(structArg);
|
|
304
314
|
if (firstParam?.type === FuncParameterType.destructuredObject) for (const { name, alias } of firstParam.props) {
|
|
305
315
|
const argInfo = positionalArgs.find((a) => a.schemaKey === name);
|
|
306
316
|
if (argInfo) {
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
pendingHeaderEntries.push({
|
|
312
|
-
argName,
|
|
313
|
-
header: `${getAttributesString(argInfo.type)}${argName}: ${this.resolve(undecorate(argInfo.type)).value}`
|
|
314
|
-
});
|
|
315
|
-
} else if (structArg) {
|
|
316
|
-
const propSnippet = accessProp(structArg, name);
|
|
317
|
-
if (propSnippet) argAliases.push([alias, propSnippet]);
|
|
318
|
-
}
|
|
317
|
+
const arg = createArgument(this.makeNameValid(alias), argInfo.type);
|
|
318
|
+
args.push(arg);
|
|
319
|
+
argAccess[alias] = arg.access;
|
|
320
|
+
} else if (structArg) argAccess[alias] = createArgumentPropAccess(structArg.access, name);
|
|
319
321
|
}
|
|
320
322
|
else if (firstParam?.type === FuncParameterType.identifier) {
|
|
321
323
|
const proxyEntries = [];
|
|
322
324
|
for (const a of positionalArgs) {
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
args.push(s);
|
|
325
|
+
const arg = createArgument(this.makeNameValid(`_arg_${a.schemaKey}`), a.type);
|
|
326
|
+
args.push(arg);
|
|
326
327
|
proxyEntries.push({
|
|
327
328
|
schemaKey: a.schemaKey,
|
|
328
|
-
|
|
329
|
-
type: a.type
|
|
330
|
-
});
|
|
331
|
-
pendingHeaderEntries.push({
|
|
332
|
-
argName,
|
|
333
|
-
header: `${getAttributesString(a.type)}${argName}: ${this.resolve(undecorate(a.type)).value}`
|
|
329
|
+
arg: arg.access
|
|
334
330
|
});
|
|
335
331
|
}
|
|
336
|
-
const router = new EntryInputRouter(
|
|
337
|
-
|
|
332
|
+
const router = new EntryInputRouter(structArg?.access, proxyEntries);
|
|
333
|
+
argAccess[firstParam.name] = () => snip("N/A", router, "argument");
|
|
338
334
|
} else for (const a of positionalArgs) {
|
|
339
335
|
const argName = this.makeNameValid(`_arg_${a.schemaKey}`);
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
header: `${getAttributesString(a.type)}${argName}: ${this.resolve(undecorate(a.type)).value}`
|
|
344
|
-
});
|
|
336
|
+
const arg = createArgument(argName, a.type);
|
|
337
|
+
args.push(arg);
|
|
338
|
+
argAccess[argName] = arg.access;
|
|
345
339
|
}
|
|
346
340
|
} else for (const [i, argType] of options.argTypes.entries()) {
|
|
347
341
|
const astParam = options.params[i];
|
|
348
342
|
const origin = isPtr(argType) ? argType.addressSpace === "storage" ? argType.access === "read" ? "readonly" : "mutable" : argType.addressSpace : "argument";
|
|
349
343
|
switch (astParam?.type) {
|
|
350
344
|
case FuncParameterType.identifier: {
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (snippet.value !== rawName) argAliases.push([rawName, snippet]);
|
|
345
|
+
const arg = createArgument(this.makeNameValid(astParam.name), argType, origin);
|
|
346
|
+
args.push(arg);
|
|
347
|
+
argAccess[astParam.name] = arg.access;
|
|
355
348
|
break;
|
|
356
349
|
}
|
|
357
350
|
case FuncParameterType.destructuredObject: {
|
|
358
|
-
const
|
|
359
|
-
args.push(
|
|
360
|
-
|
|
351
|
+
const objArg = createArgument(this.makeNameValid(`_arg_${i}`), argType, origin);
|
|
352
|
+
args.push(objArg);
|
|
353
|
+
for (const { name, alias } of astParam.props) argAccess[alias] = createArgumentPropAccess(objArg.access, name);
|
|
361
354
|
break;
|
|
362
355
|
}
|
|
363
|
-
case void 0: if (!(argType instanceof AutoStruct)) args.push(
|
|
356
|
+
case void 0: if (!(argType instanceof AutoStruct)) args.push({
|
|
357
|
+
name: this.makeNameValid(`_arg_${i}`),
|
|
358
|
+
access: () => {
|
|
359
|
+
throw new Error(`Unreachable: Accessing an argument that wasn't named in the function signature`);
|
|
360
|
+
},
|
|
361
|
+
decoratedType: argType,
|
|
362
|
+
used: false
|
|
363
|
+
});
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
|
-
const scope = this._itemStateStack.pushFunctionScope(options.functionType,
|
|
366
|
+
const scope = this._itemStateStack.pushFunctionScope(options.functionType, argAccess, options.returnType, options.externalMap);
|
|
367
367
|
fnScopePushed = true;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
368
|
+
let returnType;
|
|
369
|
+
const code = this.gen.functionDefinition({
|
|
370
|
+
functionType: options.functionType,
|
|
371
|
+
args,
|
|
372
|
+
body: options.body,
|
|
373
|
+
determineReturnType: () => {
|
|
374
|
+
if (returnType) return returnType;
|
|
375
|
+
returnType = options.returnType;
|
|
376
|
+
if (returnType instanceof AutoStruct) if (isWgslStruct(scope.reportedReturnTypes.values().next().value)) returnType = returnType.completeStruct;
|
|
377
|
+
else returnType = void 0;
|
|
378
|
+
if (!returnType) {
|
|
379
|
+
const returnTypes = [...scope.reportedReturnTypes];
|
|
380
|
+
if (returnTypes.length === 0) returnType = Void;
|
|
381
|
+
else {
|
|
382
|
+
const conversion = getBestConversion(returnTypes);
|
|
383
|
+
if (conversion && !conversion.hasImplicitConversions) returnType = conversion.targetType;
|
|
384
|
+
}
|
|
385
|
+
if (!returnType) throw new Error(`Expected function to have a single return type, got [${returnTypes.join(", ")}]. Cast explicitly to the desired type.`);
|
|
386
|
+
returnType = concretize(returnType);
|
|
387
|
+
if (options.functionType === "vertex" || options.functionType === "fragment") returnType = createIoSchema(returnType);
|
|
388
|
+
}
|
|
389
|
+
return returnType;
|
|
378
390
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (options.functionType === "vertex" || options.functionType === "fragment") returnType = createIoSchema(returnType);
|
|
382
|
-
}
|
|
383
|
-
if (options.entryInput) return {
|
|
384
|
-
head: `(${pendingHeaderEntries.filter(({ argName }) => isArgUsedInBody(argName, body)).map(({ header }) => header).join(", ")}) ${returnType.type !== "void" ? `-> ${getAttributesString(returnType)}${this.resolve(returnType).value} ` : ""}`,
|
|
385
|
-
body,
|
|
386
|
-
returnType
|
|
387
|
-
};
|
|
391
|
+
});
|
|
392
|
+
if (!returnType) throw new Error(`Failed to determine return type`);
|
|
388
393
|
return {
|
|
389
|
-
|
|
390
|
-
body,
|
|
394
|
+
code,
|
|
391
395
|
returnType
|
|
392
396
|
};
|
|
393
397
|
} finally {
|
|
@@ -602,13 +606,6 @@ function resolve(item, options) {
|
|
|
602
606
|
logResources: ctx.logResources
|
|
603
607
|
};
|
|
604
608
|
}
|
|
605
|
-
function isArgUsedInBody(argName, body) {
|
|
606
|
-
return (/* @__PURE__ */ new RegExp(`\\b${argName}\\b`)).test(body);
|
|
607
|
-
}
|
|
608
|
-
function resolveFunctionHeader(ctx, args, returnType) {
|
|
609
|
-
const argList = args.map((arg) => `${arg.value}: ${ctx.resolve(arg.dataType).value}`).join(", ");
|
|
610
|
-
return returnType.type !== "void" ? `(${argList}) -> ${getAttributesString(returnType)}${ctx.resolve(returnType).value} ` : `(${argList}) `;
|
|
611
|
-
}
|
|
612
609
|
|
|
613
610
|
//#endregion
|
|
614
611
|
export { ResolutionCtxImpl, resolve };
|
package/tgsl/accessIndex.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNaturallyEphemeral, isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
|
|
2
|
-
import { MatrixColumnsAccess,
|
|
2
|
+
import { MatrixColumnsAccess, isDisarray } from "../data/dataTypes.js";
|
|
3
3
|
import { isEphemeralSnippet, snip } from "../data/snippet.js";
|
|
4
4
|
import { isKnownAtComptime } from "../types.js";
|
|
5
5
|
import { stitch } from "../core/resolve/stitch.js";
|
|
@@ -37,7 +37,7 @@ function accessIndex(target, indexArg) {
|
|
|
37
37
|
return snip(stitch`${target.value.matrix}[${index}]`, propType, target.origin);
|
|
38
38
|
}
|
|
39
39
|
if (target.dataType.type in indexableTypeToResult) throw new Error("The only way of accessing matrix elements in TypeGPU functions is through the 'columns' property.");
|
|
40
|
-
if (isKnownAtComptime(target) && isKnownAtComptime(index)
|
|
40
|
+
if (isKnownAtComptime(target) && isKnownAtComptime(index)) return coerceToSnippet(target.value[index.value]);
|
|
41
41
|
if (isWgslStruct(target.dataType) && isKnownAtComptime(index) && typeof index.value === "string") return accessProp(target, index.value);
|
|
42
42
|
}
|
|
43
43
|
|
package/tgsl/accessProp.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $gpuCallable } from "../shared/symbols.js";
|
|
2
2
|
import { isMat, isNaturallyEphemeral, isPtr, isVec, isWgslArray, isWgslStruct } from "../data/wgslTypes.js";
|
|
3
3
|
import { InfixDispatch, MatrixColumnsAccess, UnknownData, isUnstruct, undecorate } from "../data/dataTypes.js";
|
|
4
|
-
import { isEphemeralSnippet, snip } from "../data/snippet.js";
|
|
4
|
+
import { isEphemeralSnippet, isSnippet, snip } from "../data/snippet.js";
|
|
5
5
|
import { isKnownAtComptime } from "../types.js";
|
|
6
6
|
import { stitch } from "../core/resolve/stitch.js";
|
|
7
7
|
import { derefSnippet } from "../data/ref.js";
|
|
@@ -92,7 +92,12 @@ function accessProp(target, propName) {
|
|
|
92
92
|
if (!result) return;
|
|
93
93
|
return snip(stitch`${target}.${result.prop}`, result.type, "argument");
|
|
94
94
|
}
|
|
95
|
-
if (target.dataType instanceof EntryInputRouter)
|
|
95
|
+
if (target.dataType instanceof EntryInputRouter) {
|
|
96
|
+
const result = target.dataType.accessProp(propName);
|
|
97
|
+
if (isSnippet(result)) return result;
|
|
98
|
+
if (result) return accessProp(result.target, result.prop);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
96
101
|
if (isPtr(target.dataType)) {
|
|
97
102
|
const derefed = derefSnippet(target);
|
|
98
103
|
if (propName === "$") return derefed;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { $internal } from "../../shared/symbols.js";
|
|
2
2
|
import { Void } from "../../data/wgslTypes.js";
|
|
3
|
-
import { UnknownData } from "../../data/dataTypes.js";
|
|
3
|
+
import { UnknownData, unptr } from "../../data/dataTypes.js";
|
|
4
4
|
import { snip } from "../../data/snippet.js";
|
|
5
|
+
import { invariant } from "../../errors.js";
|
|
5
6
|
import { stitch } from "../../core/resolve/stitch.js";
|
|
7
|
+
import { convertToCommonType } from "../conversion.js";
|
|
6
8
|
import { u32 } from "../../data/numeric.js";
|
|
7
|
-
import {
|
|
9
|
+
import { concretizeSnippet } from "../generationHelpers.js";
|
|
8
10
|
import { struct } from "../../data/struct.js";
|
|
9
11
|
import { shaderStageSlot } from "../../core/slot/internalSlots.js";
|
|
10
12
|
import { arrayOf } from "../../data/array.js";
|
|
@@ -61,16 +63,21 @@ var LogGeneratorImpl = class {
|
|
|
61
63
|
console.warn(`Unsupported log method '${op}'.`);
|
|
62
64
|
return fallbackSnippet;
|
|
63
65
|
}
|
|
64
|
-
const concreteArgs = concretizeSnippets(args);
|
|
65
66
|
const id = this.#firstUnusedId++;
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const concreteArgsWithStrings = args.map((arg) => {
|
|
68
|
+
if (arg.dataType === UnknownData) return arg;
|
|
69
|
+
const converted = convertToCommonType(ctx, [arg], [unptr(arg.dataType)])?.[0];
|
|
70
|
+
invariant(converted, `Internal error. Expected type ${arg.dataType} to be convertible to ${unptr(arg.dataType)}`);
|
|
71
|
+
return converted;
|
|
72
|
+
}).map(concretizeSnippet);
|
|
73
|
+
const concreteArgs = concreteArgsWithStrings.filter((arg) => arg.dataType !== UnknownData);
|
|
74
|
+
const logFn = createLoggingFunction(id, concreteArgs.map((e) => e.dataType), this.#dataBuffer, this.#indexBuffer, this.#options);
|
|
75
|
+
const functionSnippet = snip(stitch`${ctx.resolve(logFn).value}(${concreteArgs})`, Void, "runtime");
|
|
69
76
|
this.#logIdToMeta.set(id, {
|
|
70
77
|
op,
|
|
71
|
-
argTypes
|
|
78
|
+
argTypes: concreteArgsWithStrings.map((e) => e?.dataType === UnknownData ? e?.value : e?.dataType)
|
|
72
79
|
});
|
|
73
|
-
return
|
|
80
|
+
return functionSnippet;
|
|
74
81
|
}
|
|
75
82
|
get logResources() {
|
|
76
83
|
return this.#firstUnusedId === 1 ? void 0 : {
|
package/tgsl/conversion.js
CHANGED
|
@@ -90,14 +90,19 @@ function getImplicitConversionRank(src, dest) {
|
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
if ((trueSrc.type === "u32" || trueSrc.type === "i32") && trueDst.type === "abstractFloat") return {
|
|
94
|
+
rank: 1,
|
|
95
|
+
action: "cast",
|
|
96
|
+
targetType: trueDst.concretized
|
|
97
|
+
};
|
|
93
98
|
if (trueSrc.type === "abstractFloat") {
|
|
94
|
-
if (trueDst.type === "
|
|
99
|
+
if (trueDst.type === "i32") return {
|
|
95
100
|
rank: 2,
|
|
96
101
|
action: "cast",
|
|
97
102
|
targetType: trueDst
|
|
98
103
|
};
|
|
99
|
-
if (trueDst.type === "
|
|
100
|
-
rank:
|
|
104
|
+
if (trueDst.type === "u32") return {
|
|
105
|
+
rank: 3,
|
|
101
106
|
action: "cast",
|
|
102
107
|
targetType: trueDst
|
|
103
108
|
};
|
|
@@ -113,6 +118,10 @@ function getConversionRank(src, dest, allowImplicit) {
|
|
|
113
118
|
function findBestType(types, uniqueTypes, allowImplicit) {
|
|
114
119
|
let bestResult;
|
|
115
120
|
for (const targetType of uniqueTypes) {
|
|
121
|
+
/**
|
|
122
|
+
* The type we end up converting to. Will be different than `targetType` if `targetType === abstractFloat`
|
|
123
|
+
*/
|
|
124
|
+
let destType = targetType;
|
|
116
125
|
const details = [];
|
|
117
126
|
let sum = 0;
|
|
118
127
|
for (const sourceType of types) {
|
|
@@ -120,9 +129,10 @@ function findBestType(types, uniqueTypes, allowImplicit) {
|
|
|
120
129
|
sum += conversion.rank;
|
|
121
130
|
if (conversion.rank === Number.POSITIVE_INFINITY) break;
|
|
122
131
|
details.push(conversion);
|
|
132
|
+
if (conversion.action === "cast") destType = conversion.targetType;
|
|
123
133
|
}
|
|
124
134
|
if (sum < (bestResult?.sum ?? Number.POSITIVE_INFINITY)) bestResult = {
|
|
125
|
-
type:
|
|
135
|
+
type: destType,
|
|
126
136
|
details,
|
|
127
137
|
sum
|
|
128
138
|
};
|
|
@@ -168,7 +178,7 @@ function convertToCommonType(ctx, values, restrictTo, verbose = true) {
|
|
|
168
178
|
if (DEV && Array.isArray(restrictTo) && restrictTo.length === 0) console.warn("convertToCommonType was called with an empty restrictTo array, which prevents any conversions from being made. If you intend to allow all conversions, pass undefined instead. If this was intended call the function conditionally since the result will always be undefined.");
|
|
169
179
|
const conversion = getBestConversion(types, restrictTo);
|
|
170
180
|
if (!conversion) return;
|
|
171
|
-
if ((TEST || DEV) && verbose && conversion.hasImplicitConversions) console.warn(`Implicit conversions from [\n${values.map((v) => ` ${v.value}: ${safeStringify(v.dataType)}`).join(",\n")}\n] to ${conversion.targetType.type} are supported, but not recommended.
|
|
181
|
+
if ((TEST || DEV) && verbose && conversion.hasImplicitConversions) console.warn(`Implicit conversions from [\n${values.map((v) => ` ${ctx.resolveSnippet(v).value}: ${safeStringify(v.dataType)}`).join(",\n")}\n] to ${conversion.targetType.type} are supported, but not recommended.
|
|
172
182
|
Consider using explicit conversions instead.`);
|
|
173
183
|
return values.map((value, index) => {
|
|
174
184
|
const action = conversion.actions[index];
|
package/tgsl/forOfUtils.js
CHANGED
|
@@ -33,12 +33,20 @@ function getElementType(elementSnippet, iterableSnippet) {
|
|
|
33
33
|
}
|
|
34
34
|
function getRangeSnippets(ctx, iterableSnippet, unroll = false) {
|
|
35
35
|
const { value, dataType } = iterableSnippet;
|
|
36
|
-
if (isTgpuRange(value))
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
if (isTgpuRange(value)) {
|
|
37
|
+
const { start, end, step } = value;
|
|
38
|
+
const dataType$1 = [
|
|
39
|
+
start,
|
|
40
|
+
end,
|
|
41
|
+
step
|
|
42
|
+
].every((v) => v >= 0) ? u32 : i32;
|
|
43
|
+
return {
|
|
44
|
+
start: snip(start, dataType$1, "constant"),
|
|
45
|
+
end: snip(end, dataType$1, "constant"),
|
|
46
|
+
step: snip(step, dataType$1, "constant"),
|
|
47
|
+
comparison: step < 0 ? ">" : "<"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
42
50
|
if (!unroll && isEphemeralSnippet(iterableSnippet)) throw new Error(`\`for ... of ...\` loops only support std.range or iterables stored in variables.
|
|
43
51
|
-----
|
|
44
52
|
You can wrap iterable with \`tgpu.unroll(...)\`. If iterable is known at comptime, the loop will be unrolled.
|
|
@@ -25,9 +25,6 @@ function concretize(type) {
|
|
|
25
25
|
function concretizeSnippet(snippet) {
|
|
26
26
|
return snip(snippet.value, concretize(snippet.dataType), snippet.origin);
|
|
27
27
|
}
|
|
28
|
-
function concretizeSnippets(args) {
|
|
29
|
-
return args.map(concretizeSnippet);
|
|
30
|
-
}
|
|
31
28
|
function coerceToSnippet(value) {
|
|
32
29
|
if (isSnippet(value)) return value;
|
|
33
30
|
if (isRef(value)) throw new Error("Cannot use refs (d.ref(...)) from the outer scope.");
|
|
@@ -66,4 +63,4 @@ var ArrayExpression = class {
|
|
|
66
63
|
};
|
|
67
64
|
|
|
68
65
|
//#endregion
|
|
69
|
-
export { ArrayExpression, coerceToSnippet, concretize,
|
|
66
|
+
export { ArrayExpression, coerceToSnippet, concretize, concretizeSnippet, numericLiteralToSnippet };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ResolvedSnippet, Snippet } from "../data/snippet.js";
|
|
2
2
|
import { GenerationCtx } from "./generationHelpers.js";
|
|
3
|
-
import "./shaderGenerator_members.js";
|
|
3
|
+
import { FunctionDefinitionOptions } from "./shaderGenerator_members.js";
|
|
4
4
|
import { BaseData } from "../data/wgslTypes.js";
|
|
5
|
-
import { Block } from "tinyest";
|
|
6
5
|
|
|
7
6
|
//#region src/tgsl/shaderGenerator.d.ts
|
|
8
7
|
|
|
@@ -14,7 +13,7 @@ import { Block } from "tinyest";
|
|
|
14
13
|
*/
|
|
15
14
|
interface ShaderGenerator {
|
|
16
15
|
initGenerator(ctx: GenerationCtx): void;
|
|
17
|
-
functionDefinition(
|
|
16
|
+
functionDefinition(options: FunctionDefinitionOptions): string;
|
|
18
17
|
typeInstantiation(schema: BaseData, args: readonly Snippet[]): ResolvedSnippet;
|
|
19
18
|
typeAnnotation(schema: BaseData): string;
|
|
20
19
|
}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Origin, Snippet } from "../data/snippet.js";
|
|
2
|
+
import { FunctionArgument, ResolutionCtx, TgpuShaderStage } from "../types.js";
|
|
3
|
+
import { BaseData } from "../data/wgslTypes.js";
|
|
4
|
+
import { UnknownData } from "../data/dataTypes.js";
|
|
5
|
+
import { Block } from "tinyest";
|
|
6
|
+
|
|
7
|
+
//#region src/tgsl/shaderGenerator_members.d.ts
|
|
8
|
+
interface FunctionDefinitionOptions {
|
|
9
|
+
readonly functionType: 'normal' | TgpuShaderStage;
|
|
10
|
+
readonly args: readonly FunctionArgument[];
|
|
11
|
+
readonly body: Block;
|
|
12
|
+
determineReturnType(): BaseData;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { FunctionDefinitionOptions };
|
package/tgsl/wgslGenerator.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Origin, ResolvedSnippet, Snippet } from "../data/snippet.js";
|
|
2
2
|
import { GenerationCtx } from "./generationHelpers.js";
|
|
3
|
+
import { FunctionDefinitionOptions } from "./shaderGenerator_members.js";
|
|
3
4
|
import { ShaderGenerator } from "./shaderGenerator.js";
|
|
4
5
|
import { BaseData, StorableData } from "../data/wgslTypes.js";
|
|
5
6
|
import { UnknownData } from "../data/dataTypes.js";
|
|
@@ -22,7 +23,7 @@ declare class WgslGenerator implements ShaderGenerator {
|
|
|
22
23
|
*/
|
|
23
24
|
_typedExpression(expression: tinyest.Expression, expectedType: BaseData | BaseData[]): Snippet;
|
|
24
25
|
_expression(expression: tinyest.Expression): Snippet;
|
|
25
|
-
functionDefinition(
|
|
26
|
+
functionDefinition(options: FunctionDefinitionOptions): string;
|
|
26
27
|
/**
|
|
27
28
|
* Generates a WGSL type string for the given data type, and adds necessary
|
|
28
29
|
* definitions to the shader preamble. This shouldn't be called directly, only
|
|
@@ -30,6 +31,7 @@ declare class WgslGenerator implements ShaderGenerator {
|
|
|
30
31
|
*/
|
|
31
32
|
typeAnnotation(data: BaseData): string;
|
|
32
33
|
typeInstantiation(schema: BaseData, args: readonly Snippet[]): ResolvedSnippet;
|
|
34
|
+
_return(statement: tinyest.Return): string;
|
|
33
35
|
_statement(statement: tinyest.Statement): string;
|
|
34
36
|
}
|
|
35
37
|
//#endregion
|
package/tgsl/wgslGenerator.js
CHANGED
|
@@ -13,6 +13,7 @@ import { convertStructValues, convertToCommonType, tryConvertSnippet } from "./c
|
|
|
13
13
|
import { bool, i32, u32 } from "../data/numeric.js";
|
|
14
14
|
import { ArrayExpression, coerceToSnippet, concretize, numericLiteralToSnippet } from "./generationHelpers.js";
|
|
15
15
|
import { vec2u, vec3u, vec4u } from "../data/vector.js";
|
|
16
|
+
import { getAttributesString } from "../data/attributes.js";
|
|
16
17
|
import { AutoStruct } from "../data/autoStruct.js";
|
|
17
18
|
import { add, div, mul, neg, sub } from "../std/operators.js";
|
|
18
19
|
import { accessProp } from "./accessProp.js";
|
|
@@ -292,7 +293,7 @@ ${this.ctx.pre}}`;
|
|
|
292
293
|
if (!accessed) {
|
|
293
294
|
const targetStr = this.ctx.resolve(target.value, target.dataType).value;
|
|
294
295
|
const propertyStr = this.ctx.resolve(property.value, property.dataType).value;
|
|
295
|
-
throw new Error(`
|
|
296
|
+
throw new Error(`Index access '${targetStr}[${propertyStr}]' is invalid. If the value is an array, to address this, consider one of the following approaches: (1) declare the array using 'tgpu.const', (2) store the array in a buffer, or (3) define the array within the GPU function scope.`);
|
|
296
297
|
}
|
|
297
298
|
return accessed;
|
|
298
299
|
}
|
|
@@ -422,8 +423,13 @@ ${this.ctx.pre}}`;
|
|
|
422
423
|
if (expression[0] === NODE.preUpdate) throw new Error("Cannot use pre-updates in TypeGPU functions.");
|
|
423
424
|
assertExhaustive(expression);
|
|
424
425
|
}
|
|
425
|
-
functionDefinition(
|
|
426
|
-
|
|
426
|
+
functionDefinition(options) {
|
|
427
|
+
const body = this._block(options.body);
|
|
428
|
+
const returnType = options.determineReturnType();
|
|
429
|
+
const argList = options.args.filter((arg) => arg.used || options.functionType === "normal").map((arg) => {
|
|
430
|
+
return `${getAttributesString(arg.decoratedType)}${arg.name}: ${this.ctx.resolve(arg.decoratedType).value}`;
|
|
431
|
+
}).join(", ");
|
|
432
|
+
return `${returnType.type !== "void" ? `(${argList}) -> ${getAttributesString(returnType)}${this.ctx.resolve(returnType).value} ` : `(${argList}) `}${body}`;
|
|
427
433
|
}
|
|
428
434
|
/**
|
|
429
435
|
* Generates a WGSL type string for the given data type, and adds necessary
|
|
@@ -437,6 +443,28 @@ ${this.ctx.pre}}`;
|
|
|
437
443
|
if (args.length === 1 && args[0]?.dataType === schema) return snip(stitch`${args[0]}`, schema, fallthroughCopyOrigin(args[0].origin));
|
|
438
444
|
return snip(stitch`${this.ctx.resolve(schema).value}(${args})`, schema, "runtime");
|
|
439
445
|
}
|
|
446
|
+
_return(statement) {
|
|
447
|
+
const returnNode = statement[1];
|
|
448
|
+
if (returnNode !== void 0) {
|
|
449
|
+
const expectedReturnType = this.ctx.topFunctionReturnType;
|
|
450
|
+
let returnSnippet = expectedReturnType ? this._typedExpression(returnNode, expectedReturnType) : this._expression(returnNode);
|
|
451
|
+
if (returnSnippet.value instanceof RefOperator) throw new WgslTypeError(stitch`Cannot return references, returning '${returnSnippet.value.snippet}'`);
|
|
452
|
+
if (returnSnippet.origin === "argument" && !isNaturallyEphemeral(returnSnippet.dataType) && this.ctx.topFunctionScope?.functionType === "normal") throw new WgslTypeError(stitch`Cannot return references to arguments, returning '${returnSnippet}'. Copy the argument before returning it.`);
|
|
453
|
+
if (!expectedReturnType && !isEphemeralSnippet(returnSnippet) && returnSnippet.origin !== "this-function") {
|
|
454
|
+
const str = this.ctx.resolve(returnSnippet.value, returnSnippet.dataType).value;
|
|
455
|
+
const typeStr = this.ctx.resolve(unptr(returnSnippet.dataType)).value;
|
|
456
|
+
throw new WgslTypeError(`'return ${str};' is invalid, cannot return references.
|
|
457
|
+
-----
|
|
458
|
+
Try 'return ${typeStr}(${str});' instead.
|
|
459
|
+
-----`);
|
|
460
|
+
}
|
|
461
|
+
returnSnippet = tryConvertSnippet(this.ctx, returnSnippet, unptr(returnSnippet.dataType), false);
|
|
462
|
+
invariant(returnSnippet.dataType !== UnknownData, "Return type should be known");
|
|
463
|
+
this.ctx.reportReturnType(returnSnippet.dataType);
|
|
464
|
+
return stitch`${this.ctx.pre}return ${returnSnippet};`;
|
|
465
|
+
}
|
|
466
|
+
return `${this.ctx.pre}return;`;
|
|
467
|
+
}
|
|
440
468
|
_statement(statement) {
|
|
441
469
|
if (typeof statement === "string") {
|
|
442
470
|
const id = this._identifier(statement);
|
|
@@ -444,28 +472,7 @@ ${this.ctx.pre}}`;
|
|
|
444
472
|
return resolved$1 ? `${this.ctx.pre}${resolved$1};` : "";
|
|
445
473
|
}
|
|
446
474
|
if (typeof statement === "boolean") return `${this.ctx.pre}${statement ? "true" : "false"};`;
|
|
447
|
-
if (statement[0] === NODE.return)
|
|
448
|
-
const returnNode = statement[1];
|
|
449
|
-
if (returnNode !== void 0) {
|
|
450
|
-
const expectedReturnType = this.ctx.topFunctionReturnType;
|
|
451
|
-
let returnSnippet = expectedReturnType ? this._typedExpression(returnNode, expectedReturnType) : this._expression(returnNode);
|
|
452
|
-
if (returnSnippet.value instanceof RefOperator) throw new WgslTypeError(stitch`Cannot return references, returning '${returnSnippet.value.snippet}'`);
|
|
453
|
-
if (returnSnippet.origin === "argument" && !isNaturallyEphemeral(returnSnippet.dataType) && this.ctx.topFunctionScope?.functionType === "normal") throw new WgslTypeError(stitch`Cannot return references to arguments, returning '${returnSnippet}'. Copy the argument before returning it.`);
|
|
454
|
-
if (!expectedReturnType && !isEphemeralSnippet(returnSnippet) && returnSnippet.origin !== "this-function") {
|
|
455
|
-
const str = this.ctx.resolve(returnSnippet.value, returnSnippet.dataType).value;
|
|
456
|
-
const typeStr = this.ctx.resolve(unptr(returnSnippet.dataType)).value;
|
|
457
|
-
throw new WgslTypeError(`'return ${str};' is invalid, cannot return references.
|
|
458
|
-
-----
|
|
459
|
-
Try 'return ${typeStr}(${str});' instead.
|
|
460
|
-
-----`);
|
|
461
|
-
}
|
|
462
|
-
returnSnippet = tryConvertSnippet(this.ctx, returnSnippet, unptr(returnSnippet.dataType), false);
|
|
463
|
-
invariant(returnSnippet.dataType !== UnknownData, "Return type should be known");
|
|
464
|
-
this.ctx.reportReturnType(returnSnippet.dataType);
|
|
465
|
-
return stitch`${this.ctx.pre}return ${returnSnippet};`;
|
|
466
|
-
}
|
|
467
|
-
return `${this.ctx.pre}return;`;
|
|
468
|
-
}
|
|
475
|
+
if (statement[0] === NODE.return) return this._return(statement);
|
|
469
476
|
if (statement[0] === NODE.if) {
|
|
470
477
|
const [_, condNode, consNode, altNode] = statement;
|
|
471
478
|
const condition = this._typedExpression(condNode, bool);
|
|
@@ -600,7 +607,7 @@ ${this.ctx.pre}else ${alternate}`;
|
|
|
600
607
|
const index = this.ctx.makeNameValid("i");
|
|
601
608
|
const forHeaderStr = stitch`${this.ctx.pre}for (var ${index} = ${range.start}; ${index} ${range.comparison} ${range.end}; ${index} += ${range.step})`;
|
|
602
609
|
let bodyStr = "";
|
|
603
|
-
if (isTgpuRange(iterableSnippet.value)) bodyStr = this._block(blockified, { [originalLoopVarName]: snip(index,
|
|
610
|
+
if (isTgpuRange(iterableSnippet.value)) bodyStr = this._block(blockified, { [originalLoopVarName]: snip(index, range.start.dataType, "runtime") });
|
|
604
611
|
else {
|
|
605
612
|
this.ctx.indent();
|
|
606
613
|
ctxIndent = true;
|
package/types.d.ts
CHANGED
|
@@ -49,11 +49,17 @@ type ItemLayer = {
|
|
|
49
49
|
type: 'item';
|
|
50
50
|
usedSlots: Set<TgpuSlot<unknown>>;
|
|
51
51
|
};
|
|
52
|
+
type FunctionArgumentAccess = () => Snippet | undefined;
|
|
53
|
+
interface FunctionArgument {
|
|
54
|
+
name: string;
|
|
55
|
+
access: FunctionArgumentAccess;
|
|
56
|
+
decoratedType: BaseData;
|
|
57
|
+
used: boolean;
|
|
58
|
+
}
|
|
52
59
|
type FunctionScopeLayer = {
|
|
53
60
|
type: 'functionScope';
|
|
54
61
|
functionType: 'normal' | 'compute' | 'vertex' | 'fragment';
|
|
55
|
-
|
|
56
|
-
argAliases: Record<string, Snippet>;
|
|
62
|
+
argAccess: Record<string, FunctionArgumentAccess>;
|
|
57
63
|
externalMap: Record<string, unknown>;
|
|
58
64
|
/**
|
|
59
65
|
* The return type of the function. If undefined, the type should be inferred
|
|
@@ -81,7 +87,7 @@ interface ItemStateStack {
|
|
|
81
87
|
readonly topFunctionScope: FunctionScopeLayer | undefined;
|
|
82
88
|
pushItem(): void;
|
|
83
89
|
pushSlotBindings(pairs: SlotValuePair[]): void;
|
|
84
|
-
pushFunctionScope(functionType: 'normal' | TgpuShaderStage,
|
|
90
|
+
pushFunctionScope(functionType: 'normal' | TgpuShaderStage, argAccess: Record<string, FunctionArgumentAccess>,
|
|
85
91
|
/**
|
|
86
92
|
* The return type of the function. If undefined, the type should be inferred
|
|
87
93
|
* from the implementation (relevant for shellless functions).
|
|
@@ -217,8 +223,7 @@ interface ResolutionCtx {
|
|
|
217
223
|
*/
|
|
218
224
|
resolveSnippet(snippet: Snippet): ResolvedSnippet;
|
|
219
225
|
fnToWgsl(options: FnToWgslOptions): {
|
|
220
|
-
|
|
221
|
-
body: Wgsl;
|
|
226
|
+
code: string;
|
|
222
227
|
returnType: BaseData;
|
|
223
228
|
};
|
|
224
229
|
withVaryingLocations<T>(locations: Record<string, number>, callback: () => T): T;
|
|
@@ -261,4 +266,4 @@ type AnyFn = (...args: never[]) => unknown;
|
|
|
261
266
|
type DualFn<T extends AnyFn> = T & GPUCallable<Parameters<T>>;
|
|
262
267
|
type BindableBufferUsage = 'uniform' | 'readonly' | 'mutable';
|
|
263
268
|
//#endregion
|
|
264
|
-
export { BindableBufferUsage, DualFn, FunctionScopeLayer, GPUCallable, ResolutionCtx, ResolvableObject, SelfResolvable, TgpuShaderStage, Wgsl, WithCast };
|
|
269
|
+
export { BindableBufferUsage, DualFn, FunctionArgument, FunctionScopeLayer, GPUCallable, ResolutionCtx, ResolvableObject, SelfResolvable, TgpuShaderStage, Wgsl, WithCast };
|