typegpu 0.10.0 → 0.10.2
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/{chunk-BYypO7fO.js → _virtual/_rolldown/runtime.js} +1 -1
- package/builtin.d.ts +50 -0
- package/builtin.js +37 -0
- package/common/fullScreenTriangle.d.ts +26 -0
- package/common/fullScreenTriangle.js +36 -0
- package/common/index.d.ts +2 -3
- package/common/index.js +3 -4
- package/core/buffer/buffer.d.ts +74 -0
- package/core/buffer/buffer.js +197 -0
- package/core/buffer/bufferShorthand.d.ts +48 -0
- package/core/buffer/bufferShorthand.js +49 -0
- package/core/buffer/bufferUsage.d.ts +45 -0
- package/core/buffer/bufferUsage.js +163 -0
- package/core/constant/tgpuConstant.d.ts +28 -0
- package/core/constant/tgpuConstant.js +67 -0
- package/core/declare/tgpuDeclare.d.ts +18 -0
- package/core/declare/tgpuDeclare.js +40 -0
- package/core/function/autoIO.d.ts +37 -0
- package/core/function/autoIO.js +87 -0
- package/core/function/comptime.d.ts +39 -0
- package/core/function/comptime.js +51 -0
- package/core/function/createCallableSchema.js +42 -0
- package/core/function/dualImpl.js +54 -0
- package/core/function/extractArgs.js +204 -0
- package/core/function/fnCore.js +79 -0
- package/core/function/fnTypes.d.ts +34 -0
- package/core/function/ioSchema.d.ts +10 -0
- package/core/function/ioSchema.js +30 -0
- package/core/function/shelllessImpl.d.ts +28 -0
- package/core/function/shelllessImpl.js +23 -0
- package/core/function/templateUtils.js +13 -0
- package/core/function/tgpuComputeFn.d.ts +49 -0
- package/core/function/tgpuComputeFn.js +62 -0
- package/core/function/tgpuFn.d.ts +52 -0
- package/core/function/tgpuFn.js +170 -0
- package/core/function/tgpuFragmentFn.d.ts +68 -0
- package/core/function/tgpuFragmentFn.js +68 -0
- package/core/function/tgpuVertexFn.d.ts +55 -0
- package/core/function/tgpuVertexFn.js +65 -0
- package/core/pipeline/applyPipelineState.js +37 -0
- package/core/pipeline/computePipeline.d.ts +58 -0
- package/core/pipeline/computePipeline.js +226 -0
- package/core/pipeline/connectAttachmentToShader.js +26 -0
- package/core/pipeline/connectTargetsToShader.js +29 -0
- package/core/pipeline/limitsOverflow.js +13 -0
- package/core/pipeline/renderPipeline.d.ts +266 -0
- package/core/pipeline/renderPipeline.js +471 -0
- package/core/pipeline/timeable.d.ts +23 -0
- package/core/pipeline/timeable.js +61 -0
- package/core/pipeline/typeGuards.js +29 -0
- package/core/querySet/querySet.d.ts +22 -0
- package/core/querySet/querySet.js +103 -0
- package/core/rawCodeSnippet/tgpuRawCodeSnippet.d.ts +59 -0
- package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +96 -0
- package/core/resolve/externals.d.ts +10 -0
- package/core/resolve/externals.js +58 -0
- package/core/resolve/namespace.d.ts +38 -0
- package/core/resolve/namespace.js +41 -0
- package/core/resolve/resolveData.js +146 -0
- package/core/resolve/stitch.js +25 -0
- package/core/resolve/tgpuResolve.d.ts +151 -0
- package/core/resolve/tgpuResolve.js +68 -0
- package/core/root/configurableImpl.js +18 -0
- package/core/root/init.d.ts +69 -0
- package/core/root/init.js +457 -0
- package/core/root/rootTypes.d.ts +622 -0
- package/core/sampler/sampler.d.ts +35 -0
- package/core/sampler/sampler.js +116 -0
- package/core/simulate/tgpuSimulate.d.ts +36 -0
- package/core/simulate/tgpuSimulate.js +76 -0
- package/core/slot/accessor.d.ts +13 -0
- package/core/slot/accessor.js +97 -0
- package/core/slot/internalSlots.js +7 -0
- package/core/slot/lazy.d.ts +6 -0
- package/core/slot/lazy.js +42 -0
- package/core/slot/slot.d.ts +6 -0
- package/core/slot/slot.js +40 -0
- package/core/slot/slotTypes.d.ts +92 -0
- package/core/slot/slotTypes.js +21 -0
- package/core/texture/externalTexture.d.ts +12 -0
- package/core/texture/externalTexture.js +48 -0
- package/core/texture/texture.d.ts +118 -0
- package/core/texture/texture.js +312 -0
- package/core/texture/textureFormats.d.ts +29 -0
- package/core/texture/textureFormats.js +99 -0
- package/core/texture/textureProps.d.ts +11 -0
- package/core/texture/textureUtils.js +224 -0
- package/core/texture/usageExtension.d.ts +21 -0
- package/core/texture/usageExtension.js +21 -0
- package/core/unroll/tgpuUnroll.d.ts +13 -0
- package/core/unroll/tgpuUnroll.js +36 -0
- package/core/valueProxyUtils.js +44 -0
- package/core/variable/tgpuVariable.d.ts +38 -0
- package/core/variable/tgpuVariable.js +101 -0
- package/core/vertexLayout/connectAttributesToShader.js +59 -0
- package/core/vertexLayout/vertexAttribute.d.ts +29 -0
- package/core/vertexLayout/vertexLayout.d.ts +19 -0
- package/core/vertexLayout/vertexLayout.js +103 -0
- package/data/alignIO.js +15 -0
- package/data/alignmentOf.d.ts +10 -0
- package/data/alignmentOf.js +88 -0
- package/data/array.d.ts +28 -0
- package/data/array.js +48 -0
- package/data/atomic.d.ts +15 -0
- package/data/atomic.js +25 -0
- package/data/attributes.d.ts +121 -0
- package/data/attributes.js +145 -0
- package/data/autoStruct.d.ts +3 -0
- package/data/autoStruct.js +83 -0
- package/data/compiledIO.js +231 -0
- package/data/dataIO.js +549 -0
- package/data/dataTypes.d.ts +115 -0
- package/data/dataTypes.js +97 -0
- package/data/deepEqual.d.ts +25 -0
- package/data/deepEqual.js +58 -0
- package/data/disarray.d.ts +34 -0
- package/data/disarray.js +52 -0
- package/data/getLongestContiguousPrefix.d.ts +10 -0
- package/data/getLongestContiguousPrefix.js +15 -0
- package/data/index.d.ts +26 -4
- package/data/index.js +27 -7
- package/data/instanceToSchema.d.ts +33 -0
- package/data/isContiguous.d.ts +10 -0
- package/data/isContiguous.js +15 -0
- package/data/matrix.d.ts +126 -0
- package/data/matrix.js +517 -0
- package/data/numberOps.js +24 -0
- package/data/numeric.d.ts +81 -0
- package/data/numeric.js +234 -0
- package/data/offsetUtils.d.ts +33 -0
- package/data/offsetUtils.js +167 -0
- package/data/offsets.js +36 -0
- package/data/partialIO.js +68 -0
- package/data/ptr.d.ts +12 -0
- package/data/ptr.js +46 -0
- package/data/ref.d.ts +37 -0
- package/data/ref.js +96 -0
- package/data/sampler.d.ts +107 -0
- package/data/sampler.js +26 -0
- package/data/schemaCallWrapper.js +32 -0
- package/data/schemaMemoryLayout.js +200 -0
- package/data/sizeOf.d.ts +10 -0
- package/data/sizeOf.js +15 -0
- package/data/snippet.d.ts +26 -0
- package/data/snippet.js +61 -0
- package/data/struct.d.ts +17 -0
- package/data/struct.js +46 -0
- package/data/texture.d.ts +292 -0
- package/{texture-Dg5ybJro.js → data/texture.js} +6 -3
- package/data/unstruct.d.ts +24 -0
- package/data/unstruct.js +43 -0
- package/data/vector.d.ts +191 -0
- package/data/vector.js +247 -0
- package/data/vectorImpl.js +516 -0
- package/data/vectorOps.js +664 -0
- package/data/vertexFormatData.d.ts +190 -0
- package/data/vertexFormatData.js +110 -0
- package/data/wgslTypes.d.ts +896 -0
- package/data/wgslTypes.js +215 -0
- package/errors.d.ts +44 -0
- package/errors.js +128 -0
- package/execMode.js +51 -0
- package/extension.d.ts +11 -0
- package/extension.js +18 -0
- package/getGPUValue.js +9 -0
- package/index.d.ts +40 -243
- package/index.js +19 -6318
- package/indexNamedExports.d.ts +38 -0
- package/mathUtils.js +13 -0
- package/memo.js +22 -0
- package/nameRegistry.d.ts +30 -0
- package/nameRegistry.js +449 -0
- package/package.js +5 -0
- package/package.json +23 -23
- package/resolutionCtx.d.ts +29 -0
- package/resolutionCtx.js +546 -0
- package/shared/env.js +13 -0
- package/shared/generators.js +14 -0
- package/shared/meta.d.ts +39 -0
- package/shared/meta.js +63 -0
- package/shared/repr.d.ts +108 -0
- package/shared/stringify.js +22 -0
- package/shared/symbols.d.ts +61 -0
- package/shared/symbols.js +71 -0
- package/shared/utilityTypes.d.ts +29 -0
- package/shared/utilityTypes.js +7 -0
- package/shared/vertexFormat.d.ts +70 -0
- package/shared/vertexFormat.js +64 -0
- package/std/array.d.ts +7 -0
- package/std/array.js +27 -0
- package/std/atomic.d.ts +19 -0
- package/std/atomic.js +113 -0
- package/std/bitcast.d.ts +10 -0
- package/std/bitcast.js +43 -0
- package/std/boolean.d.ts +127 -0
- package/std/boolean.js +274 -0
- package/std/derivative.d.ts +16 -0
- package/std/derivative.js +89 -0
- package/std/discard.d.ts +6 -0
- package/std/discard.js +16 -0
- package/std/extensions.d.ts +8 -0
- package/std/extensions.js +14 -0
- package/std/index.d.ts +15 -3
- package/std/index.js +16 -5
- package/std/matrix.d.ts +41 -0
- package/std/matrix.js +87 -0
- package/std/numeric.d.ts +254 -0
- package/std/numeric.js +847 -0
- package/std/operators.d.ts +48 -0
- package/std/operators.js +153 -0
- package/std/packing.d.ts +26 -0
- package/std/packing.js +86 -0
- package/std/subgroup.d.ts +47 -0
- package/std/subgroup.js +220 -0
- package/std/texture.d.ts +108 -0
- package/std/texture.js +197 -0
- package/tgpu.js +44 -0
- package/tgpuBindGroupLayout.d.ts +161 -0
- package/tgpuBindGroupLayout.js +271 -0
- package/tgpuUnstable.d.ts +48 -0
- package/tgpuUnstable.js +66 -0
- package/tgsl/accessIndex.js +45 -0
- package/tgsl/accessProp.js +113 -0
- package/tgsl/consoleLog/deserializers.js +117 -0
- package/tgsl/consoleLog/logGenerator.js +86 -0
- package/tgsl/consoleLog/serializers.js +225 -0
- package/tgsl/consoleLog/types.d.ts +54 -0
- package/tgsl/consoleLog/types.js +12 -0
- package/tgsl/conversion.js +200 -0
- package/tgsl/forOfUtils.js +45 -0
- package/tgsl/generationHelpers.d.ts +37 -0
- package/tgsl/generationHelpers.js +67 -0
- package/tgsl/math.js +45 -0
- package/tgsl/shaderGenerator.d.ts +18 -0
- package/tgsl/shellless.d.ts +11 -0
- package/tgsl/shellless.js +53 -0
- package/tgsl/wgslGenerator.js +585 -0
- package/types.d.ts +255 -0
- package/types.js +43 -0
- package/unwrapper.d.ts +27 -0
- package/wgslExtensions.d.ts +5 -0
- package/wgslExtensions.js +18 -0
- package/builtin-ClEnM-Ye.js +0 -818
- package/builtin-ClEnM-Ye.js.map +0 -1
- package/common/index.d.ts.map +0 -1
- package/common/index.js.map +0 -1
- package/data/index.d.ts.map +0 -1
- package/data/index.js.map +0 -1
- package/deepEqual-yZXvaV2C.js +0 -413
- package/deepEqual-yZXvaV2C.js.map +0 -1
- package/extensions-0SFbU9FH.js +0 -2032
- package/extensions-0SFbU9FH.js.map +0 -1
- package/fullScreenTriangle-MdLGaAMR.js +0 -543
- package/fullScreenTriangle-MdLGaAMR.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/indexNamedExports-Cdy7USiY.d.ts +0 -5696
- package/indexNamedExports-Cdy7USiY.d.ts.map +0 -1
- package/operators-HTxa_0k9.js +0 -4156
- package/operators-HTxa_0k9.js.map +0 -1
- package/std/index.d.ts.map +0 -1
- package/std/index.js.map +0 -1
- package/texture-Dg5ybJro.js.map +0 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
//#region src/core/function/extractArgs.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extracts info about arguments of a given WGSL function string.
|
|
4
|
+
* @example
|
|
5
|
+
* const code = `
|
|
6
|
+
* fn add(a: i32, @location(0) b: i32, c) -> i32 {
|
|
7
|
+
* return a + b + c;
|
|
8
|
+
* }`;
|
|
9
|
+
*
|
|
10
|
+
* extractArgs(code);
|
|
11
|
+
* // {
|
|
12
|
+
* // args: [
|
|
13
|
+
* // { identifier: 'a', attributes: [], type: 'i32' },
|
|
14
|
+
* // { identifier: 'b', attributes: ['@location(0)'], type: 'i32' },
|
|
15
|
+
* // { identifier: 'c', attributes: [], type: undefined }
|
|
16
|
+
* // ],
|
|
17
|
+
* // ret: { type: 'i32', attributes: [] },
|
|
18
|
+
* // range: { begin: 11, end: 51 }
|
|
19
|
+
* // }
|
|
20
|
+
*/
|
|
21
|
+
function extractArgs(rawCode) {
|
|
22
|
+
const { strippedCode, argRange: range } = strip(rawCode);
|
|
23
|
+
const code = new ParsableString(strippedCode);
|
|
24
|
+
code.consume("(");
|
|
25
|
+
const args = [];
|
|
26
|
+
while (!code.isAt(")")) {
|
|
27
|
+
const attributes = [];
|
|
28
|
+
while (code.isAt("@")) {
|
|
29
|
+
code.parseUntil(closingParenthesis, parentheses);
|
|
30
|
+
code.consume(")");
|
|
31
|
+
attributes.push(code.lastParsed);
|
|
32
|
+
}
|
|
33
|
+
code.parseUntil(identifierEndSymbols);
|
|
34
|
+
const identifier = code.lastParsed;
|
|
35
|
+
let maybeType;
|
|
36
|
+
if (code.isAt(":")) {
|
|
37
|
+
code.consume(":");
|
|
38
|
+
code.parseUntil(typeEndSymbols, angleBrackets);
|
|
39
|
+
maybeType = code.lastParsed;
|
|
40
|
+
}
|
|
41
|
+
args.push({
|
|
42
|
+
identifier,
|
|
43
|
+
attributes,
|
|
44
|
+
type: maybeType
|
|
45
|
+
});
|
|
46
|
+
if (code.isAt(",")) code.consume(",");
|
|
47
|
+
}
|
|
48
|
+
code.consume(")");
|
|
49
|
+
let maybeRet;
|
|
50
|
+
if (code.isAt("->")) {
|
|
51
|
+
code.consume("->");
|
|
52
|
+
const attributes = [];
|
|
53
|
+
while (code.isAt("@")) {
|
|
54
|
+
code.parseUntil(closingParenthesis, parentheses);
|
|
55
|
+
code.consume(")");
|
|
56
|
+
attributes.push(code.lastParsed);
|
|
57
|
+
}
|
|
58
|
+
maybeRet = {
|
|
59
|
+
type: code.str.slice(code.pos),
|
|
60
|
+
attributes
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
args,
|
|
65
|
+
ret: maybeRet,
|
|
66
|
+
range: {
|
|
67
|
+
begin: range[0],
|
|
68
|
+
end: range[1]
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Strips comments, whitespaces, the name and the body of the function.
|
|
74
|
+
* @example
|
|
75
|
+
* const code = `
|
|
76
|
+
* fn add( a, // first argument
|
|
77
|
+
* @location(0) b : i32 ) -> i32 {
|
|
78
|
+
* return a + b; // returns the sum
|
|
79
|
+
* }`;
|
|
80
|
+
*
|
|
81
|
+
* strip(code); // "(a,@location(0)b:i32)->i32"
|
|
82
|
+
*/
|
|
83
|
+
function strip(rawCode) {
|
|
84
|
+
const code = new ParsableString(rawCode);
|
|
85
|
+
let strippedCode = "";
|
|
86
|
+
let argsStart;
|
|
87
|
+
while (!code.isFinished()) {
|
|
88
|
+
if (code.isAt(blankSpaces)) {
|
|
89
|
+
code.advanceBy(1);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (code.isAt("//")) {
|
|
93
|
+
code.consume("//");
|
|
94
|
+
code.parseUntil(lineBreaks);
|
|
95
|
+
code.advanceBy(1);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (code.isAt("/*")) {
|
|
99
|
+
code.parseUntil(openingCommentBlock, commentBlocks);
|
|
100
|
+
code.consume("*/");
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (code.isAt("{")) return {
|
|
104
|
+
strippedCode,
|
|
105
|
+
argRange: [argsStart, code.pos]
|
|
106
|
+
};
|
|
107
|
+
if (code.isAt("(") && argsStart === void 0) argsStart = code.pos;
|
|
108
|
+
if (argsStart !== void 0) strippedCode += code.str[code.pos];
|
|
109
|
+
code.advanceBy(1);
|
|
110
|
+
}
|
|
111
|
+
throw new Error("Invalid wgsl code!");
|
|
112
|
+
}
|
|
113
|
+
var ParsableString = class {
|
|
114
|
+
#parseStartPos;
|
|
115
|
+
#pos;
|
|
116
|
+
constructor(str) {
|
|
117
|
+
this.str = str;
|
|
118
|
+
this.#pos = 0;
|
|
119
|
+
}
|
|
120
|
+
get pos() {
|
|
121
|
+
return this.#pos;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* This property is equivalent to the substring of `this.str`
|
|
125
|
+
* from the position of the last `parseUntil` call, to the current position.
|
|
126
|
+
*/
|
|
127
|
+
get lastParsed() {
|
|
128
|
+
if (this.#parseStartPos === void 0) throw new Error("Parse was not called yet!");
|
|
129
|
+
return this.str.slice(this.#parseStartPos, this.pos);
|
|
130
|
+
}
|
|
131
|
+
isFinished() {
|
|
132
|
+
return this.#pos >= this.str.length;
|
|
133
|
+
}
|
|
134
|
+
isAt(substr) {
|
|
135
|
+
if (typeof substr === "string") {
|
|
136
|
+
for (let i = 0; i < substr.length; i++) if (this.str[this.#pos + i] !== substr[i]) return false;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
for (const elem of substr) if (this.isAt(elem)) return true;
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @param toFind a set of strings either of which satisfy the search.
|
|
144
|
+
* @param brackets a pair of brackets that has to be closed for result to be valid. This includes the found character(s).
|
|
145
|
+
* @example
|
|
146
|
+
* // internal state:
|
|
147
|
+
* // '(@attribute(0) identifier: type)'
|
|
148
|
+
* // ^
|
|
149
|
+
* this.parse(new Set(')'), ['(', ')']);
|
|
150
|
+
* // internal state:
|
|
151
|
+
* // '(@attribute(0) identifier: type)'
|
|
152
|
+
* // ^
|
|
153
|
+
*/
|
|
154
|
+
parseUntil(toFind, brackets) {
|
|
155
|
+
this.#parseStartPos = this.#pos;
|
|
156
|
+
let openedBrackets = 0;
|
|
157
|
+
while (this.#pos < this.str.length) {
|
|
158
|
+
if (brackets && this.isAt(brackets[0])) openedBrackets += 1;
|
|
159
|
+
if (brackets && this.isAt(brackets[1])) openedBrackets -= 1;
|
|
160
|
+
if (openedBrackets === 0) {
|
|
161
|
+
if (this.isAt(toFind)) return this.#pos;
|
|
162
|
+
}
|
|
163
|
+
this.#pos += 1;
|
|
164
|
+
}
|
|
165
|
+
throw new Error("Reached the end of the string without finding a match!");
|
|
166
|
+
}
|
|
167
|
+
advanceBy(steps) {
|
|
168
|
+
this.#pos += steps;
|
|
169
|
+
}
|
|
170
|
+
consume(str) {
|
|
171
|
+
if (!this.isAt(str)) throw new Error(`Expected '${str}' at position ${this.#pos}, but found '${this.str.slice(this.#pos, this.#pos + str.length)}'`);
|
|
172
|
+
this.advanceBy(str.length);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const lineBreaks = new Set([
|
|
176
|
+
"\n",
|
|
177
|
+
"\v",
|
|
178
|
+
"\f",
|
|
179
|
+
"\r",
|
|
180
|
+
"
",
|
|
181
|
+
"\u2028",
|
|
182
|
+
"\u2029"
|
|
183
|
+
]);
|
|
184
|
+
const blankSpaces = new Set([
|
|
185
|
+
...lineBreaks,
|
|
186
|
+
" ",
|
|
187
|
+
" ",
|
|
188
|
+
"",
|
|
189
|
+
""
|
|
190
|
+
]);
|
|
191
|
+
const closingParenthesis = new Set([")"]);
|
|
192
|
+
const identifierEndSymbols = new Set([
|
|
193
|
+
":",
|
|
194
|
+
",",
|
|
195
|
+
")"
|
|
196
|
+
]);
|
|
197
|
+
const typeEndSymbols = new Set([",", ")"]);
|
|
198
|
+
const openingCommentBlock = new Set(["*/"]);
|
|
199
|
+
const parentheses = ["(", ")"];
|
|
200
|
+
const angleBrackets = ["<", ">"];
|
|
201
|
+
const commentBlocks = ["/*", "*/"];
|
|
202
|
+
|
|
203
|
+
//#endregion
|
|
204
|
+
export { extractArgs };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { $getNameForward } from "../../shared/symbols.js";
|
|
2
|
+
import { getMetaData, getName } from "../../shared/meta.js";
|
|
3
|
+
import { Void, isWgslData, isWgslStruct } from "../../data/wgslTypes.js";
|
|
4
|
+
import { undecorate } from "../../data/dataTypes.js";
|
|
5
|
+
import { snip } from "../../data/snippet.js";
|
|
6
|
+
import { MissingLinksError } from "../../errors.js";
|
|
7
|
+
import { getAttributesString } from "../../data/attributes.js";
|
|
8
|
+
import { applyExternals, replaceExternalsInWgsl } from "../resolve/externals.js";
|
|
9
|
+
import { extractArgs } from "./extractArgs.js";
|
|
10
|
+
|
|
11
|
+
//#region src/core/function/fnCore.ts
|
|
12
|
+
function createFnCore(implementation, fnAttribute = "") {
|
|
13
|
+
/**
|
|
14
|
+
* External application has to be deferred until resolution because
|
|
15
|
+
* some externals can reference the owner function which has not been
|
|
16
|
+
* initialized yet (like when accessing the Output struct of a vertex
|
|
17
|
+
* entry fn).
|
|
18
|
+
*/
|
|
19
|
+
const externalsToApply = [];
|
|
20
|
+
return {
|
|
21
|
+
[$getNameForward]: typeof implementation === "function" ? implementation : void 0,
|
|
22
|
+
applyExternals(newExternals) {
|
|
23
|
+
externalsToApply.push(newExternals);
|
|
24
|
+
},
|
|
25
|
+
resolve(ctx, argTypes, returnType) {
|
|
26
|
+
const externalMap = {};
|
|
27
|
+
for (const externals of externalsToApply) applyExternals(externalMap, externals);
|
|
28
|
+
const id = ctx.getUniqueName(this);
|
|
29
|
+
if (typeof implementation === "string") {
|
|
30
|
+
if (!returnType) throw new Error("Explicit return type is required for string implementation");
|
|
31
|
+
const replacedImpl = replaceExternalsInWgsl(ctx, externalMap, implementation);
|
|
32
|
+
let header = "";
|
|
33
|
+
let body = "";
|
|
34
|
+
if (fnAttribute !== "") {
|
|
35
|
+
const input = isWgslStruct(argTypes[0]) ? `(in: ${ctx.resolve(argTypes[0]).value})` : "()";
|
|
36
|
+
const attributes = isWgslData(returnType) ? getAttributesString(returnType) : "";
|
|
37
|
+
header = `${input} ${returnType !== Void ? isWgslStruct(returnType) ? `-> ${ctx.resolve(returnType).value}` : `-> ${attributes !== "" ? attributes : "@location(0)"} ${ctx.resolve(returnType).value}` : ""} `;
|
|
38
|
+
body = replacedImpl;
|
|
39
|
+
} else {
|
|
40
|
+
const providedArgs = extractArgs(replacedImpl);
|
|
41
|
+
if (providedArgs.args.length !== argTypes.length) throw new Error(`WGSL implementation has ${providedArgs.args.length} arguments, while the shell has ${argTypes.length} arguments.`);
|
|
42
|
+
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)}`}`;
|
|
43
|
+
body = replacedImpl.slice(providedArgs.range.end);
|
|
44
|
+
}
|
|
45
|
+
ctx.addDeclaration(`${fnAttribute}fn ${id}${header}${body}`);
|
|
46
|
+
return snip(id, returnType, "runtime");
|
|
47
|
+
}
|
|
48
|
+
const pluginData = getMetaData(implementation);
|
|
49
|
+
const pluginExternals = typeof pluginData?.externals === "function" ? pluginData.externals() : pluginData?.externals;
|
|
50
|
+
if (pluginExternals) applyExternals(externalMap, Object.fromEntries(Object.entries(pluginExternals).filter(([name]) => !(name in externalMap))));
|
|
51
|
+
const ast = pluginData?.ast;
|
|
52
|
+
if (!ast) throw new Error("Missing metadata for tgpu.fn function body (either missing 'use gpu' directive, or misconfigured `unplugin-typegpu`)");
|
|
53
|
+
const missingExternals = ast.externalNames.filter((name) => !(name in externalMap));
|
|
54
|
+
if (missingExternals.length > 0) throw new MissingLinksError(getName(this), missingExternals);
|
|
55
|
+
const maybeSecondArg = ast.params[1];
|
|
56
|
+
if (maybeSecondArg && maybeSecondArg.type === "i" && fnAttribute !== "") applyExternals(externalMap, { [maybeSecondArg.name]: undecorate(returnType) });
|
|
57
|
+
const { head, body, returnType: actualReturnType } = ctx.fnToWgsl({
|
|
58
|
+
functionType: fnAttribute.includes("@compute") ? "compute" : fnAttribute.includes("@vertex") ? "vertex" : fnAttribute.includes("@fragment") ? "fragment" : "normal",
|
|
59
|
+
argTypes,
|
|
60
|
+
params: ast.params,
|
|
61
|
+
returnType,
|
|
62
|
+
body: ast.body,
|
|
63
|
+
externalMap
|
|
64
|
+
});
|
|
65
|
+
ctx.addDeclaration(`${fnAttribute}fn ${id}${ctx.resolve(head).value}${ctx.resolve(body).value}`);
|
|
66
|
+
return snip(id, actualReturnType, "runtime");
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function checkAndReturnType(ctx, name, wgslType, jsType) {
|
|
71
|
+
const resolvedJsType = ctx.resolve(jsType).value.replace(/\s/g, "");
|
|
72
|
+
if (!wgslType) return resolvedJsType;
|
|
73
|
+
const resolvedWgslType = wgslType.replace(/\s/g, "");
|
|
74
|
+
if (resolvedWgslType !== resolvedJsType) throw new Error(`Type mismatch between TGPU shell and WGSL code string: ${name}, JS type "${resolvedJsType}", WGSL type "${resolvedWgslType}".`);
|
|
75
|
+
return wgslType;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { createFnCore };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BuiltinClipDistances } from "../../builtin.js";
|
|
2
|
+
import { AnyAttribute } from "../../data/attributes.js";
|
|
3
|
+
import { Bool, Decorated, F16, F32, I32, U32, Vec2f, Vec2h, Vec2i, Vec2u, Vec3f, Vec3h, Vec3i, Vec3u, Vec4f, Vec4h, Vec4i, Vec4u, Void } from "../../data/wgslTypes.js";
|
|
4
|
+
import { Infer } from "../../shared/repr.js";
|
|
5
|
+
import "tinyest";
|
|
6
|
+
|
|
7
|
+
//#region src/core/function/fnTypes.d.ts
|
|
8
|
+
type AnyFn = (...args: never[]) => unknown;
|
|
9
|
+
type InferArgs<T extends unknown[]> = { [Idx in keyof T]: Infer<T[Idx]> };
|
|
10
|
+
type InheritTupleValues<T, From> = { [K in keyof T]: K extends keyof From ? From[K] : never };
|
|
11
|
+
/**
|
|
12
|
+
* Returns a type that has arg and return types of `T`, but argument
|
|
13
|
+
* names of `From`
|
|
14
|
+
*
|
|
15
|
+
* Wrapped in an object type with `result` prop just so that it's easier
|
|
16
|
+
* to remove InheritArgNames<...> from Intellisense with Prettify<T>['result']
|
|
17
|
+
*/
|
|
18
|
+
type InheritArgNames<T extends AnyFn, From extends AnyFn> = {
|
|
19
|
+
result: (...args: Parameters<((...args: InheritTupleValues<Parameters<From>, Parameters<T>>) => ReturnType<T>) & T>) => ReturnType<T>;
|
|
20
|
+
};
|
|
21
|
+
type InferImplSchema<ImplSchema extends AnyFn> = (...args: InferArgs<Parameters<ImplSchema>>) => Infer<ReturnType<ImplSchema>>;
|
|
22
|
+
type Implementation<ImplSchema extends AnyFn = AnyFn> = string | InferImplSchema<ImplSchema>;
|
|
23
|
+
type BaseIOData = Bool | F32 | F16 | I32 | U32 | Vec2f | Vec3f | Vec4f | Vec2h | Vec3h | Vec4h | Vec2i | Vec3i | Vec4i | Vec2u | Vec3u | Vec4u;
|
|
24
|
+
type IOData = BaseIOData | Decorated<BaseIOData, AnyAttribute[]> | BuiltinClipDistances;
|
|
25
|
+
type IORecord<TElementType extends IOData = IOData> = Record<string, TElementType>;
|
|
26
|
+
/**
|
|
27
|
+
* Used for I/O definitions of entry functions.
|
|
28
|
+
*/
|
|
29
|
+
type IOLayout<TElementType extends IOData = IOData> = TElementType | IORecord<TElementType> | Void;
|
|
30
|
+
type InferIO<T> = T extends {
|
|
31
|
+
type: string;
|
|
32
|
+
} ? Infer<T> : T extends Record<string, unknown> ? { [K in keyof T]: Infer<T[K]> } : T;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { AnyFn, BaseIOData, IOLayout, IORecord, Implementation, InferArgs, InferIO, InferImplSchema, InheritArgNames };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Decorate, HasCustomLocation, IsBuiltin } from "../../data/attributes.js";
|
|
2
|
+
import { BaseData, Location, WgslStruct } from "../../data/wgslTypes.js";
|
|
3
|
+
|
|
4
|
+
//#region src/core/function/ioSchema.d.ts
|
|
5
|
+
type WithLocations<T extends Record<string, BaseData>> = { [Key in keyof T]: IsBuiltin<T[Key]> extends true ? T[Key] : HasCustomLocation<T[Key]> extends true ? T[Key] : Decorate<T[Key], Location> };
|
|
6
|
+
type IOLayoutToSchema<T> = T extends BaseData ? HasCustomLocation<T> extends true ? T : Decorate<T, Location<0>> : T extends Record<string, BaseData> ? WgslStruct<WithLocations<T>> : T extends {
|
|
7
|
+
type: 'void';
|
|
8
|
+
} ? void : never;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { IOLayoutToSchema };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isVoid } from "../../data/wgslTypes.js";
|
|
2
|
+
import { getCustomLocation, isData } from "../../data/dataTypes.js";
|
|
3
|
+
import { isBuiltin, location } from "../../data/attributes.js";
|
|
4
|
+
import { INTERNAL_createStruct } from "../../data/struct.js";
|
|
5
|
+
|
|
6
|
+
//#region src/core/function/ioSchema.ts
|
|
7
|
+
function withLocations(members, locations = {}) {
|
|
8
|
+
let nextLocation = 0;
|
|
9
|
+
const usedCustomLocations = /* @__PURE__ */ new Set();
|
|
10
|
+
return Object.fromEntries(Object.entries(members ?? {}).map(([key, member]) => {
|
|
11
|
+
const customLocation = getCustomLocation(member);
|
|
12
|
+
if (customLocation !== void 0) {
|
|
13
|
+
if (usedCustomLocations.has(customLocation)) throw new Error("Duplicate custom location attributes found");
|
|
14
|
+
usedCustomLocations.add(customLocation);
|
|
15
|
+
}
|
|
16
|
+
return [key, member];
|
|
17
|
+
}).map(([key, member]) => {
|
|
18
|
+
if (isBuiltin(member)) return [key, member];
|
|
19
|
+
if (getCustomLocation(member) !== void 0) return [key, member];
|
|
20
|
+
if (locations[key]) return [key, location(locations[key], member)];
|
|
21
|
+
while (usedCustomLocations.has(nextLocation)) nextLocation++;
|
|
22
|
+
return [key, location(nextLocation++, member)];
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
function createIoSchema(layout, locations = {}) {
|
|
26
|
+
return isData(layout) ? isVoid(layout) ? layout : isBuiltin(layout) ? layout : getCustomLocation(layout) !== void 0 ? layout : location(0, layout) : INTERNAL_createStruct(withLocations(layout, locations), false);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createIoSchema };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { $getNameForward } from "../../shared/symbols.js";
|
|
2
|
+
import { SelfResolvable } from "../../types.js";
|
|
3
|
+
import { BaseData } from "../../data/wgslTypes.js";
|
|
4
|
+
|
|
5
|
+
//#region src/core/function/shelllessImpl.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Shell-less functions are possible because we can infer the signature based solely on the context
|
|
8
|
+
* around the function.
|
|
9
|
+
*
|
|
10
|
+
* ## Arguments
|
|
11
|
+
* The snippets of the function's arguments are used to infer the types of the function's arguments.
|
|
12
|
+
* We only care that the arguments are of a concrete type (we concretize them if they're not). We
|
|
13
|
+
* cache these signatures based on the argument types, so that we can reuse them across calls.
|
|
14
|
+
*
|
|
15
|
+
* ## Return type
|
|
16
|
+
* In shelled functions, the return type is known when generating the body, but in the case of shell-less functions,
|
|
17
|
+
* we gather candidates for return types when visiting return statement nodes, and try to unify them into one type
|
|
18
|
+
* before generating the signature.
|
|
19
|
+
*
|
|
20
|
+
* TODO: This behavior can be refined by considering the "expected type" of the function call expression.
|
|
21
|
+
*/
|
|
22
|
+
interface ShelllessImpl extends SelfResolvable {
|
|
23
|
+
readonly resourceType: 'shellless-impl';
|
|
24
|
+
readonly argTypes: BaseData[];
|
|
25
|
+
readonly [$getNameForward]: unknown;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { ShelllessImpl };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { $getNameForward, $internal, $resolve } from "../../shared/symbols.js";
|
|
2
|
+
import { getName } from "../../shared/meta.js";
|
|
3
|
+
import { createFnCore } from "./fnCore.js";
|
|
4
|
+
|
|
5
|
+
//#region src/core/function/shelllessImpl.ts
|
|
6
|
+
function createShelllessImpl(argTypes, implementation) {
|
|
7
|
+
const core = createFnCore(implementation, "");
|
|
8
|
+
return {
|
|
9
|
+
[$internal]: true,
|
|
10
|
+
[$getNameForward]: core,
|
|
11
|
+
resourceType: "shellless-impl",
|
|
12
|
+
argTypes,
|
|
13
|
+
[$resolve](ctx) {
|
|
14
|
+
return core.resolve(ctx, argTypes, void 0);
|
|
15
|
+
},
|
|
16
|
+
toString() {
|
|
17
|
+
return `fn*:${getName(core) ?? "<unnamed>"}(${argTypes.map((t) => t.toString()).join(", ")})`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createShelllessImpl };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/core/function/templateUtils.ts
|
|
2
|
+
function stripTemplate(arg, ...values) {
|
|
3
|
+
return isTemplateStringsArray(arg) ? templateLiteralIdentity(arg, ...values) : arg;
|
|
4
|
+
}
|
|
5
|
+
function isTemplateStringsArray(value) {
|
|
6
|
+
return Array.isArray(value) && "raw" in value && Array.isArray(value.raw) && value.raw.every((item) => typeof item === "string");
|
|
7
|
+
}
|
|
8
|
+
function templateLiteralIdentity(strings, ...values) {
|
|
9
|
+
return strings.slice(1).reduce((acc, elem, index) => `${acc}${values[index]}${elem}`, strings[0]);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { stripTemplate };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TgpuNamable } from "../../shared/meta.js";
|
|
2
|
+
import { $internal } from "../../shared/symbols.js";
|
|
3
|
+
import { AnyComputeBuiltin } from "../../builtin.js";
|
|
4
|
+
import { IORecord, InferIO } from "./fnTypes.js";
|
|
5
|
+
import { IOLayoutToSchema } from "./ioSchema.js";
|
|
6
|
+
import { Void } from "../../data/wgslTypes.js";
|
|
7
|
+
|
|
8
|
+
//#region src/core/function/tgpuComputeFn.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Describes a compute entry function signature (its arguments, return type and workgroup size)
|
|
11
|
+
*/
|
|
12
|
+
type TgpuComputeFnShellHeader<ComputeIn extends IORecord<AnyComputeBuiltin>> = {
|
|
13
|
+
readonly argTypes: [IOLayoutToSchema<ComputeIn>] | [];
|
|
14
|
+
readonly returnType: Void;
|
|
15
|
+
readonly workgroupSize: [number, number, number];
|
|
16
|
+
readonly entryPoint: 'compute';
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Describes a compute entry function signature (its arguments, return type and workgroup size).
|
|
20
|
+
* Allows creating tgpu compute functions by calling this shell
|
|
21
|
+
* and passing the implementation (as WGSL string or JS function) as the argument.
|
|
22
|
+
*/
|
|
23
|
+
type TgpuComputeFnShell<ComputeIn extends IORecord<AnyComputeBuiltin>> = TgpuComputeFnShellHeader<ComputeIn> &
|
|
24
|
+
/**
|
|
25
|
+
* Creates a type-safe implementation of this signature
|
|
26
|
+
*/
|
|
27
|
+
((implementation: (input: InferIO<ComputeIn>) => undefined) => TgpuComputeFn<ComputeIn>) &
|
|
28
|
+
/**
|
|
29
|
+
* @param implementation
|
|
30
|
+
* Raw WGSL function implementation with header and body
|
|
31
|
+
* without `fn` keyword and function name
|
|
32
|
+
* e.g. `"(x: f32) -> f32 { return x; }"`;
|
|
33
|
+
*/
|
|
34
|
+
((implementation: string) => TgpuComputeFn<ComputeIn>) & ((strings: TemplateStringsArray, ...values: unknown[]) => TgpuComputeFn<ComputeIn>);
|
|
35
|
+
interface TgpuComputeFn<ComputeIn extends IORecord<AnyComputeBuiltin> = any> extends TgpuNamable {
|
|
36
|
+
readonly [$internal]: true;
|
|
37
|
+
readonly shell: TgpuComputeFnShellHeader<ComputeIn>;
|
|
38
|
+
$uses(dependencyMap: Record<string, unknown>): this;
|
|
39
|
+
}
|
|
40
|
+
declare function computeFn(options: {
|
|
41
|
+
workgroupSize: number[];
|
|
42
|
+
}): TgpuComputeFnShell<{}>;
|
|
43
|
+
declare function computeFn<ComputeIn extends IORecord<AnyComputeBuiltin>>(options: {
|
|
44
|
+
in: ComputeIn;
|
|
45
|
+
workgroupSize: number[];
|
|
46
|
+
}): TgpuComputeFnShell<ComputeIn>;
|
|
47
|
+
declare function isTgpuComputeFn<ComputeIn extends IORecord<AnyComputeBuiltin>>(value: unknown): value is TgpuComputeFn<ComputeIn>;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { TgpuComputeFn, TgpuComputeFnShell, computeFn, isTgpuComputeFn };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { $getNameForward, $internal, $resolve } from "../../shared/symbols.js";
|
|
2
|
+
import { getName, isNamable, setName } from "../../shared/meta.js";
|
|
3
|
+
import { Void } from "../../data/wgslTypes.js";
|
|
4
|
+
import { createIoSchema } from "./ioSchema.js";
|
|
5
|
+
import { createFnCore } from "./fnCore.js";
|
|
6
|
+
import { stripTemplate } from "./templateUtils.js";
|
|
7
|
+
import { shaderStageSlot } from "../slot/internalSlots.js";
|
|
8
|
+
|
|
9
|
+
//#region src/core/function/tgpuComputeFn.ts
|
|
10
|
+
/**
|
|
11
|
+
* Creates a shell of a typed entry function for the compute shader stage. Any function
|
|
12
|
+
* that implements this shell can perform general-purpose computation.
|
|
13
|
+
*
|
|
14
|
+
* @param options.in
|
|
15
|
+
* Record with builtins used by the compute shader.
|
|
16
|
+
* @param options.workgroupSize
|
|
17
|
+
* Size of blocks that the thread grid will be divided into (up to 3 dimensions).
|
|
18
|
+
*/
|
|
19
|
+
function computeFn(options) {
|
|
20
|
+
const shell = {
|
|
21
|
+
argTypes: options.in && Object.keys(options.in).length !== 0 ? [createIoSchema(options.in)] : [],
|
|
22
|
+
returnType: Void,
|
|
23
|
+
workgroupSize: [
|
|
24
|
+
options.workgroupSize[0] ?? 1,
|
|
25
|
+
options.workgroupSize[1] ?? 1,
|
|
26
|
+
options.workgroupSize[2] ?? 1
|
|
27
|
+
],
|
|
28
|
+
entryPoint: "compute"
|
|
29
|
+
};
|
|
30
|
+
const call = (arg, ...values) => createComputeFn(shell, options.workgroupSize, stripTemplate(arg, ...values));
|
|
31
|
+
return Object.assign(call, shell);
|
|
32
|
+
}
|
|
33
|
+
function isTgpuComputeFn(value) {
|
|
34
|
+
return value?.shell?.entryPoint === "compute";
|
|
35
|
+
}
|
|
36
|
+
function createComputeFn(shell, workgroupSize, implementation) {
|
|
37
|
+
const core = createFnCore(implementation, `@compute @workgroup_size(${workgroupSize.join(", ")}) `);
|
|
38
|
+
const inputType = shell.argTypes[0];
|
|
39
|
+
return {
|
|
40
|
+
shell,
|
|
41
|
+
$uses(newExternals) {
|
|
42
|
+
core.applyExternals(newExternals);
|
|
43
|
+
return this;
|
|
44
|
+
},
|
|
45
|
+
[$internal]: true,
|
|
46
|
+
[$getNameForward]: core,
|
|
47
|
+
$name(newLabel) {
|
|
48
|
+
setName(this, newLabel);
|
|
49
|
+
if (isNamable(inputType)) inputType.$name(`${newLabel}_Input`);
|
|
50
|
+
return this;
|
|
51
|
+
},
|
|
52
|
+
[$resolve](ctx) {
|
|
53
|
+
return ctx.withSlots([[shaderStageSlot, "compute"]], () => core.resolve(ctx, shell.argTypes, shell.returnType));
|
|
54
|
+
},
|
|
55
|
+
toString() {
|
|
56
|
+
return `computeFn:${getName(core) ?? "<unnamed>"}`;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { computeFn, isTgpuComputeFn };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TgpuNamable } from "../../shared/meta.js";
|
|
2
|
+
import { $internal, $providing } from "../../shared/symbols.js";
|
|
3
|
+
import { Prettify } from "../../shared/utilityTypes.js";
|
|
4
|
+
import { AnyFn, Implementation, InferArgs, InferImplSchema, InheritArgNames } from "./fnTypes.js";
|
|
5
|
+
import { Providing } from "../slot/slotTypes.js";
|
|
6
|
+
import { Withable } from "../root/rootTypes.js";
|
|
7
|
+
import { DualFn } from "../../types.js";
|
|
8
|
+
import { BaseData, Void } from "../../data/wgslTypes.js";
|
|
9
|
+
import { Infer } from "../../shared/repr.js";
|
|
10
|
+
|
|
11
|
+
//#region src/core/function/tgpuFn.d.ts
|
|
12
|
+
/**
|
|
13
|
+
* Describes a function signature (its arguments and return type)
|
|
14
|
+
*/
|
|
15
|
+
type TgpuFnShellHeader<Args extends BaseData[], Return extends BaseData> = {
|
|
16
|
+
readonly [$internal]: true;
|
|
17
|
+
readonly argTypes: Args;
|
|
18
|
+
readonly returnType: Return;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Describes a function signature (its arguments and return type).
|
|
22
|
+
* Allows creating tgpu functions by calling this shell
|
|
23
|
+
* and passing the implementation (as WGSL string or JS function) as the argument.
|
|
24
|
+
*/
|
|
25
|
+
type TgpuFnShell<Args extends BaseData[], Return extends BaseData> = TgpuFnShellHeader<Args, Return> & (<T extends (...args: InferArgs<Args>) => Infer<Return>>(implementation: T) => TgpuFn<Prettify<InheritArgNames<(...args: Args) => Return, T>>['result']>) & ((implementation: string) => TgpuFn<(...args: Args) => Return>) & ((strings: TemplateStringsArray, ...values: unknown[]) => TgpuFn<(...args: Args) => Return>);
|
|
26
|
+
interface TgpuFnBase<ImplSchema extends AnyFn> extends TgpuNamable, Withable<TgpuFn<ImplSchema>> {
|
|
27
|
+
[$internal]: {
|
|
28
|
+
implementation: Implementation<ImplSchema>;
|
|
29
|
+
};
|
|
30
|
+
readonly resourceType: 'function';
|
|
31
|
+
readonly shell: TgpuFnShellHeader<Parameters<ImplSchema>, Extract<ReturnType<ImplSchema>, BaseData>>;
|
|
32
|
+
readonly [$providing]?: Providing | undefined;
|
|
33
|
+
$uses(dependencyMap: Record<string, unknown>): this;
|
|
34
|
+
}
|
|
35
|
+
type TgpuFn<ImplSchema extends AnyFn = (...args: any[]) => any> = DualFn<InferImplSchema<ImplSchema>> & TgpuFnBase<ImplSchema>;
|
|
36
|
+
/**
|
|
37
|
+
* A function wrapper that allows providing slot and accessor overrides for shellless functions
|
|
38
|
+
*/
|
|
39
|
+
interface TgpuGenericFn<T extends AnyFn> extends TgpuNamable, Withable<TgpuGenericFn<T>> {
|
|
40
|
+
readonly [$internal]: {
|
|
41
|
+
inner: T;
|
|
42
|
+
};
|
|
43
|
+
readonly [$providing]?: Providing | undefined;
|
|
44
|
+
readonly resourceType: 'generic-function';
|
|
45
|
+
(...args: Parameters<T>): ReturnType<T>;
|
|
46
|
+
}
|
|
47
|
+
declare function fn<Args extends BaseData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, Void>;
|
|
48
|
+
declare function fn<Args extends BaseData[] | [], Return extends BaseData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
|
|
49
|
+
declare function fn<T extends AnyFn>(inner: T): TgpuGenericFn<T>;
|
|
50
|
+
declare function isTgpuFn<Args extends BaseData[] | [], Return extends BaseData>(value: unknown): value is TgpuFn<(...args: Args) => Return>;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { TgpuFn, TgpuFnShell, TgpuGenericFn, fn, isTgpuFn };
|