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
package/resolutionCtx.js
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import { $internal, $providing, $resolve, isMarkedInternal } from "./shared/symbols.js";
|
|
2
|
+
import { getName, hasTinyestMetadata, setName } from "./shared/meta.js";
|
|
3
|
+
import { Void, isPtr, isWgslArray, isWgslStruct } from "./data/wgslTypes.js";
|
|
4
|
+
import { UnknownData, isData } from "./data/dataTypes.js";
|
|
5
|
+
import { snip } from "./data/snippet.js";
|
|
6
|
+
import { MissingSlotValueError, ResolutionError, WgslTypeError, invariant } from "./errors.js";
|
|
7
|
+
import { isLazy, isProviding, isSlot } from "./core/slot/slotTypes.js";
|
|
8
|
+
import { CodegenState, NormalState, isSelfResolvable } from "./types.js";
|
|
9
|
+
import { provideCtx, topLevelState } from "./execMode.js";
|
|
10
|
+
import { stitch } from "./core/resolve/stitch.js";
|
|
11
|
+
import { safeStringify } from "./shared/stringify.js";
|
|
12
|
+
import { getBestConversion } from "./tgsl/conversion.js";
|
|
13
|
+
import { bool } from "./data/numeric.js";
|
|
14
|
+
import { getAttributesString } from "./data/attributes.js";
|
|
15
|
+
import { createIoSchema } from "./core/function/ioSchema.js";
|
|
16
|
+
import { AutoStruct } from "./data/autoStruct.js";
|
|
17
|
+
import { coerceToSnippet, concretize, numericLiteralToSnippet } from "./tgsl/generationHelpers.js";
|
|
18
|
+
import { accessProp } from "./tgsl/accessProp.js";
|
|
19
|
+
import { isTgpuFn } from "./core/function/tgpuFn.js";
|
|
20
|
+
import { getUniqueName } from "./core/resolve/namespace.js";
|
|
21
|
+
import { resolveData } from "./core/resolve/resolveData.js";
|
|
22
|
+
import { ConfigurableImpl } from "./core/root/configurableImpl.js";
|
|
23
|
+
import { naturalsExcept } from "./shared/generators.js";
|
|
24
|
+
import { TgpuBindGroupImpl, bindGroupLayout } from "./tgpuBindGroupLayout.js";
|
|
25
|
+
import { LogGeneratorImpl, LogGeneratorNullImpl } from "./tgsl/consoleLog/logGenerator.js";
|
|
26
|
+
import wgslGenerator from "./tgsl/wgslGenerator.js";
|
|
27
|
+
import { FuncParameterType } from "tinyest";
|
|
28
|
+
|
|
29
|
+
//#region src/resolutionCtx.ts
|
|
30
|
+
/**
|
|
31
|
+
* Inserted into bind group entry definitions that belong
|
|
32
|
+
* to the automatically generated catch-all bind group.
|
|
33
|
+
*
|
|
34
|
+
* A non-occupied group index can only be determined after
|
|
35
|
+
* every resource has been resolved, so this acts as a placeholder
|
|
36
|
+
* to be replaced with an actual numeric index at the very end
|
|
37
|
+
* of the resolution process.
|
|
38
|
+
*/
|
|
39
|
+
const CATCHALL_BIND_GROUP_IDX_MARKER = "#CATCHALL#";
|
|
40
|
+
var ItemStateStackImpl = class {
|
|
41
|
+
_stack = [];
|
|
42
|
+
_itemDepth = 0;
|
|
43
|
+
get itemDepth() {
|
|
44
|
+
return this._itemDepth;
|
|
45
|
+
}
|
|
46
|
+
get topItem() {
|
|
47
|
+
const state = this._stack[this._stack.length - 1];
|
|
48
|
+
if (!state || state.type !== "item") throw new Error("Internal error, expected item layer to be on top.");
|
|
49
|
+
return state;
|
|
50
|
+
}
|
|
51
|
+
get topFunctionScope() {
|
|
52
|
+
return this._stack.findLast((e) => e.type === "functionScope");
|
|
53
|
+
}
|
|
54
|
+
pushItem() {
|
|
55
|
+
this._itemDepth++;
|
|
56
|
+
this._stack.push({
|
|
57
|
+
type: "item",
|
|
58
|
+
usedSlots: /* @__PURE__ */ new Set()
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
pushSlotBindings(pairs) {
|
|
62
|
+
this._stack.push({
|
|
63
|
+
type: "slotBinding",
|
|
64
|
+
bindingMap: new WeakMap(pairs)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
pushFunctionScope(functionType, args, argAliases, returnType, externalMap) {
|
|
68
|
+
const scope = {
|
|
69
|
+
type: "functionScope",
|
|
70
|
+
functionType,
|
|
71
|
+
args,
|
|
72
|
+
argAliases,
|
|
73
|
+
returnType,
|
|
74
|
+
externalMap,
|
|
75
|
+
reportedReturnTypes: /* @__PURE__ */ new Set()
|
|
76
|
+
};
|
|
77
|
+
this._stack.push(scope);
|
|
78
|
+
return scope;
|
|
79
|
+
}
|
|
80
|
+
pushBlockScope() {
|
|
81
|
+
this._stack.push({
|
|
82
|
+
type: "blockScope",
|
|
83
|
+
declarations: /* @__PURE__ */ new Map(),
|
|
84
|
+
externals: /* @__PURE__ */ new Map()
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
pop(type) {
|
|
88
|
+
const layer = this._stack[this._stack.length - 1];
|
|
89
|
+
if (!layer || type && layer.type !== type) throw new Error(`Internal error, expected a ${type} layer to be on top.`);
|
|
90
|
+
const poppedValue = this._stack.pop();
|
|
91
|
+
if (type === "item") this._itemDepth--;
|
|
92
|
+
return poppedValue;
|
|
93
|
+
}
|
|
94
|
+
readSlot(slot) {
|
|
95
|
+
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
96
|
+
const layer = this._stack[i];
|
|
97
|
+
if (layer?.type === "item") layer.usedSlots.add(slot);
|
|
98
|
+
else if (layer?.type === "slotBinding") {
|
|
99
|
+
const boundValue = layer.bindingMap.get(slot);
|
|
100
|
+
if (boundValue !== void 0) return boundValue;
|
|
101
|
+
} else if (layer?.type === "functionScope" || layer?.type === "blockScope") {} else throw new Error("Unknown layer type.");
|
|
102
|
+
}
|
|
103
|
+
return slot.defaultValue;
|
|
104
|
+
}
|
|
105
|
+
getSnippetById(id) {
|
|
106
|
+
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
107
|
+
const layer = this._stack[i];
|
|
108
|
+
if (layer?.type === "functionScope") {
|
|
109
|
+
const arg = layer.args.find((a) => a.value === id);
|
|
110
|
+
if (arg !== void 0) return arg;
|
|
111
|
+
if (layer.argAliases[id]) return layer.argAliases[id];
|
|
112
|
+
const external = layer.externalMap[id];
|
|
113
|
+
if (external !== void 0 && external !== null) return coerceToSnippet(external);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (layer?.type === "blockScope") {
|
|
117
|
+
const snippet = layer.declarations.get(id) ?? layer.externals.get(id);
|
|
118
|
+
if (snippet !== void 0) return snippet;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
defineBlockVariable(id, snippet) {
|
|
123
|
+
if (snippet.dataType === UnknownData) throw Error(`Tried to define variable '${id}' of unknown type`);
|
|
124
|
+
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
125
|
+
const layer = this._stack[i];
|
|
126
|
+
if (layer?.type === "blockScope") {
|
|
127
|
+
layer.declarations.set(id, snippet);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
throw new Error("No block scope found to define a variable in.");
|
|
132
|
+
}
|
|
133
|
+
setBlockExternals(externals) {
|
|
134
|
+
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
135
|
+
const layer = this._stack[i];
|
|
136
|
+
if (layer?.type === "blockScope") {
|
|
137
|
+
Object.entries(externals).forEach(([id, snippet]) => {
|
|
138
|
+
layer.externals.set(id, snippet);
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
throw new Error("No block scope found to set externals in.");
|
|
144
|
+
}
|
|
145
|
+
clearBlockExternals() {
|
|
146
|
+
for (let i = this._stack.length - 1; i >= 0; --i) {
|
|
147
|
+
const layer = this._stack[i];
|
|
148
|
+
if (layer?.type === "blockScope") {
|
|
149
|
+
layer.externals.clear();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
throw new Error("No block scope found to clear externals in.");
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const INDENT = [
|
|
157
|
+
"",
|
|
158
|
+
" ",
|
|
159
|
+
" ",
|
|
160
|
+
" ",
|
|
161
|
+
" ",
|
|
162
|
+
" ",
|
|
163
|
+
" ",
|
|
164
|
+
" ",
|
|
165
|
+
" "
|
|
166
|
+
];
|
|
167
|
+
const N = INDENT.length - 1;
|
|
168
|
+
var IndentController = class {
|
|
169
|
+
identLevel = 0;
|
|
170
|
+
get pre() {
|
|
171
|
+
return INDENT[this.identLevel] ?? INDENT[N].repeat(this.identLevel / N) + INDENT[this.identLevel % N];
|
|
172
|
+
}
|
|
173
|
+
indent() {
|
|
174
|
+
const str = this.pre;
|
|
175
|
+
this.identLevel++;
|
|
176
|
+
return str;
|
|
177
|
+
}
|
|
178
|
+
dedent() {
|
|
179
|
+
this.identLevel--;
|
|
180
|
+
return this.pre;
|
|
181
|
+
}
|
|
182
|
+
withResetLevel(callback) {
|
|
183
|
+
const savedLevel = this.identLevel;
|
|
184
|
+
this.identLevel = 0;
|
|
185
|
+
try {
|
|
186
|
+
return callback();
|
|
187
|
+
} finally {
|
|
188
|
+
this.identLevel = savedLevel;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var ResolutionCtxImpl = class {
|
|
193
|
+
#namespaceInternal;
|
|
194
|
+
#shaderGenerator;
|
|
195
|
+
_indentController = new IndentController();
|
|
196
|
+
_itemStateStack = new ItemStateStackImpl();
|
|
197
|
+
#modeStack = [];
|
|
198
|
+
_declarations = [];
|
|
199
|
+
_varyingLocations;
|
|
200
|
+
#currentlyResolvedItems = /* @__PURE__ */ new WeakSet();
|
|
201
|
+
#logGenerator;
|
|
202
|
+
get varyingLocations() {
|
|
203
|
+
return this._varyingLocations;
|
|
204
|
+
}
|
|
205
|
+
[$internal] = { itemStateStack: this._itemStateStack };
|
|
206
|
+
/**
|
|
207
|
+
* A map from registered bind group layouts to random strings put in
|
|
208
|
+
* place of their group index. The whole tree has to be traversed to
|
|
209
|
+
* collect every use of a typed bind group layout, since they can be
|
|
210
|
+
* explicitly imposed group indices, and they cannot collide.
|
|
211
|
+
*/
|
|
212
|
+
bindGroupLayoutsToPlaceholderMap = /* @__PURE__ */ new Map();
|
|
213
|
+
_nextFreeLayoutPlaceholderIdx = 0;
|
|
214
|
+
fixedBindings = [];
|
|
215
|
+
enableExtensions;
|
|
216
|
+
expectedType;
|
|
217
|
+
constructor(opts) {
|
|
218
|
+
this.enableExtensions = opts.enableExtensions;
|
|
219
|
+
this.#shaderGenerator = opts.shaderGenerator ?? wgslGenerator;
|
|
220
|
+
this.#logGenerator = opts.root ? new LogGeneratorImpl(opts.root) : new LogGeneratorNullImpl();
|
|
221
|
+
this.#namespaceInternal = opts.namespace[$internal];
|
|
222
|
+
}
|
|
223
|
+
getUniqueName(resource) {
|
|
224
|
+
return getUniqueName(this.#namespaceInternal, resource);
|
|
225
|
+
}
|
|
226
|
+
makeNameValid(name) {
|
|
227
|
+
return this.#namespaceInternal.nameRegistry.makeValid(name);
|
|
228
|
+
}
|
|
229
|
+
get pre() {
|
|
230
|
+
return this._indentController.pre;
|
|
231
|
+
}
|
|
232
|
+
get topFunctionScope() {
|
|
233
|
+
return this._itemStateStack.topFunctionScope;
|
|
234
|
+
}
|
|
235
|
+
get topFunctionReturnType() {
|
|
236
|
+
const scope = this._itemStateStack.topFunctionScope;
|
|
237
|
+
invariant(scope, "Internal error, expected function scope to be present.");
|
|
238
|
+
return scope.returnType;
|
|
239
|
+
}
|
|
240
|
+
get shelllessRepo() {
|
|
241
|
+
return this.#namespaceInternal.shelllessRepo;
|
|
242
|
+
}
|
|
243
|
+
indent() {
|
|
244
|
+
return this._indentController.indent();
|
|
245
|
+
}
|
|
246
|
+
dedent() {
|
|
247
|
+
return this._indentController.dedent();
|
|
248
|
+
}
|
|
249
|
+
withResetIndentLevel(callback) {
|
|
250
|
+
return this._indentController.withResetLevel(callback);
|
|
251
|
+
}
|
|
252
|
+
getById(id) {
|
|
253
|
+
const item = this._itemStateStack.getSnippetById(id);
|
|
254
|
+
if (item === void 0) return null;
|
|
255
|
+
return item;
|
|
256
|
+
}
|
|
257
|
+
defineVariable(id, snippet) {
|
|
258
|
+
this._itemStateStack.defineBlockVariable(id, snippet);
|
|
259
|
+
}
|
|
260
|
+
reportReturnType(dataType) {
|
|
261
|
+
const scope = this._itemStateStack.topFunctionScope;
|
|
262
|
+
invariant(scope, "Internal error, expected function scope to be present.");
|
|
263
|
+
scope.reportedReturnTypes.add(dataType);
|
|
264
|
+
}
|
|
265
|
+
pushBlockScope() {
|
|
266
|
+
this.#namespaceInternal.nameRegistry.pushBlockScope();
|
|
267
|
+
this._itemStateStack.pushBlockScope();
|
|
268
|
+
}
|
|
269
|
+
popBlockScope() {
|
|
270
|
+
this.#namespaceInternal.nameRegistry.popBlockScope();
|
|
271
|
+
this._itemStateStack.pop("blockScope");
|
|
272
|
+
}
|
|
273
|
+
setBlockExternals(externals) {
|
|
274
|
+
this._itemStateStack.setBlockExternals(externals);
|
|
275
|
+
}
|
|
276
|
+
clearBlockExternals() {
|
|
277
|
+
this._itemStateStack.clearBlockExternals();
|
|
278
|
+
}
|
|
279
|
+
generateLog(op, args) {
|
|
280
|
+
return this.#logGenerator.generateLog(this, op, args);
|
|
281
|
+
}
|
|
282
|
+
get logResources() {
|
|
283
|
+
return this.#logGenerator.logResources;
|
|
284
|
+
}
|
|
285
|
+
fnToWgsl(options) {
|
|
286
|
+
let fnScopePushed = false;
|
|
287
|
+
try {
|
|
288
|
+
this.#namespaceInternal.nameRegistry.pushFunctionScope();
|
|
289
|
+
const args = [];
|
|
290
|
+
const argAliases = [];
|
|
291
|
+
for (const [i, argType] of options.argTypes.entries()) {
|
|
292
|
+
const astParam = options.params[i];
|
|
293
|
+
const origin = isPtr(argType) ? argType.addressSpace === "storage" ? argType.access === "read" ? "readonly" : "mutable" : argType.addressSpace : "argument";
|
|
294
|
+
switch (astParam?.type) {
|
|
295
|
+
case FuncParameterType.identifier: {
|
|
296
|
+
const rawName = astParam.name;
|
|
297
|
+
const snippet = snip(this.makeNameValid(rawName), argType, origin);
|
|
298
|
+
args.push(snippet);
|
|
299
|
+
if (snippet.value !== rawName) argAliases.push([rawName, snippet]);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case FuncParameterType.destructuredObject: {
|
|
303
|
+
const objSnippet = snip(`_arg_${i}`, argType, origin);
|
|
304
|
+
args.push(objSnippet);
|
|
305
|
+
argAliases.push(...astParam.props.map(({ name, alias }) => [alias, accessProp(objSnippet, name)]));
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case void 0: if (!(argType instanceof AutoStruct)) args.push(snip(`_arg_${i}`, argType, origin));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const scope = this._itemStateStack.pushFunctionScope(options.functionType, args, Object.fromEntries(argAliases), options.returnType, options.externalMap);
|
|
312
|
+
fnScopePushed = true;
|
|
313
|
+
this.#shaderGenerator.initGenerator(this);
|
|
314
|
+
const body = this.#shaderGenerator.functionDefinition(options.body);
|
|
315
|
+
let returnType = options.returnType;
|
|
316
|
+
if (returnType instanceof AutoStruct) if (isWgslStruct(scope.reportedReturnTypes.values().next().value)) returnType = returnType.completeStruct;
|
|
317
|
+
else returnType = void 0;
|
|
318
|
+
if (!returnType) {
|
|
319
|
+
const returnTypes = [...scope.reportedReturnTypes];
|
|
320
|
+
if (returnTypes.length === 0) returnType = Void;
|
|
321
|
+
else {
|
|
322
|
+
const conversion = getBestConversion(returnTypes);
|
|
323
|
+
if (conversion && !conversion.hasImplicitConversions) returnType = conversion.targetType;
|
|
324
|
+
}
|
|
325
|
+
if (!returnType) throw new Error(`Expected function to have a single return type, got [${returnTypes.join(", ")}]. Cast explicitly to the desired type.`);
|
|
326
|
+
returnType = concretize(returnType);
|
|
327
|
+
if (options.functionType === "vertex" || options.functionType === "fragment") returnType = createIoSchema(returnType);
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
head: resolveFunctionHeader(this, args, returnType),
|
|
331
|
+
body,
|
|
332
|
+
returnType
|
|
333
|
+
};
|
|
334
|
+
} finally {
|
|
335
|
+
if (fnScopePushed) this._itemStateStack.pop("functionScope");
|
|
336
|
+
this.#namespaceInternal.nameRegistry.popFunctionScope();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
addDeclaration(declaration) {
|
|
340
|
+
this._declarations.push(declaration);
|
|
341
|
+
}
|
|
342
|
+
allocateLayoutEntry(layout) {
|
|
343
|
+
const memoMap = this.bindGroupLayoutsToPlaceholderMap;
|
|
344
|
+
let placeholderKey = memoMap.get(layout);
|
|
345
|
+
if (!placeholderKey) {
|
|
346
|
+
placeholderKey = `#BIND_GROUP_LAYOUT_${this._nextFreeLayoutPlaceholderIdx++}#`;
|
|
347
|
+
memoMap.set(layout, placeholderKey);
|
|
348
|
+
}
|
|
349
|
+
return placeholderKey;
|
|
350
|
+
}
|
|
351
|
+
allocateFixedEntry(layoutEntry, resource) {
|
|
352
|
+
const binding = this.fixedBindings.length;
|
|
353
|
+
this.fixedBindings.push({
|
|
354
|
+
layoutEntry,
|
|
355
|
+
resource
|
|
356
|
+
});
|
|
357
|
+
return {
|
|
358
|
+
group: CATCHALL_BIND_GROUP_IDX_MARKER,
|
|
359
|
+
binding
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
readSlot(slot) {
|
|
363
|
+
const value = this._itemStateStack.readSlot(slot);
|
|
364
|
+
if (value === void 0) throw new MissingSlotValueError(slot);
|
|
365
|
+
return value;
|
|
366
|
+
}
|
|
367
|
+
withSlots(pairs, callback) {
|
|
368
|
+
if (pairs.length === 0) return callback();
|
|
369
|
+
this._itemStateStack.pushSlotBindings(pairs);
|
|
370
|
+
try {
|
|
371
|
+
return callback();
|
|
372
|
+
} finally {
|
|
373
|
+
this._itemStateStack.pop("slotBinding");
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
withVaryingLocations(locations, callback) {
|
|
377
|
+
this._varyingLocations = locations;
|
|
378
|
+
try {
|
|
379
|
+
return callback();
|
|
380
|
+
} finally {
|
|
381
|
+
this._varyingLocations = void 0;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
withRenamed(item, name, callback) {
|
|
385
|
+
if (!name) return callback();
|
|
386
|
+
const oldName = getName(item);
|
|
387
|
+
try {
|
|
388
|
+
setName(item, name);
|
|
389
|
+
return callback();
|
|
390
|
+
} finally {
|
|
391
|
+
setName(item, oldName);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
unwrap(eventual) {
|
|
395
|
+
if (isProviding(eventual)) return this.withRenamed(eventual[$providing].inner, getName(eventual), () => this.withSlots(eventual[$providing].pairs, () => this.unwrap(eventual[$providing].inner)));
|
|
396
|
+
let maybeEventual = eventual;
|
|
397
|
+
while (true) if (isSlot(maybeEventual)) maybeEventual = this.readSlot(maybeEventual);
|
|
398
|
+
else if (isLazy(maybeEventual)) maybeEventual = this._getOrCompute(maybeEventual);
|
|
399
|
+
else break;
|
|
400
|
+
return maybeEventual;
|
|
401
|
+
}
|
|
402
|
+
_getOrCompute(lazy) {
|
|
403
|
+
const instances = this.#namespaceInternal.memoizedLazy.get(lazy) ?? [];
|
|
404
|
+
this._itemStateStack.pushItem();
|
|
405
|
+
try {
|
|
406
|
+
for (const instance of instances) if ([...instance.slotToValueMap.entries()].every(([slot, expectedValue]) => slot.areEqual(this._itemStateStack.readSlot(slot), expectedValue))) return instance.result;
|
|
407
|
+
this.pushMode(new NormalState());
|
|
408
|
+
let result;
|
|
409
|
+
try {
|
|
410
|
+
result = lazy[$internal].compute();
|
|
411
|
+
} finally {
|
|
412
|
+
this.popMode("normal");
|
|
413
|
+
}
|
|
414
|
+
const slotToValueMap = /* @__PURE__ */ new Map();
|
|
415
|
+
for (const usedSlot of this._itemStateStack.topItem.usedSlots) slotToValueMap.set(usedSlot, this._itemStateStack.readSlot(usedSlot));
|
|
416
|
+
instances.push({
|
|
417
|
+
slotToValueMap,
|
|
418
|
+
result
|
|
419
|
+
});
|
|
420
|
+
this.#namespaceInternal.memoizedLazy.set(lazy, instances);
|
|
421
|
+
return result;
|
|
422
|
+
} catch (err) {
|
|
423
|
+
if (err instanceof ResolutionError) throw err.appendToTrace(lazy);
|
|
424
|
+
throw new ResolutionError(err, [lazy]);
|
|
425
|
+
} finally {
|
|
426
|
+
this._itemStateStack.pop("item");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* @param item The item whose resolution should be either retrieved from the cache (if there is a cache hit), or resolved.
|
|
431
|
+
*/
|
|
432
|
+
_getOrInstantiate(item) {
|
|
433
|
+
const instances = this.#namespaceInternal.memoizedResolves.get(item) ?? [];
|
|
434
|
+
this._itemStateStack.pushItem();
|
|
435
|
+
try {
|
|
436
|
+
for (const instance of instances) if ([...instance.slotToValueMap.entries()].every(([slot, expectedValue]) => slot.areEqual(this._itemStateStack.readSlot(slot), expectedValue))) return instance.result;
|
|
437
|
+
let result;
|
|
438
|
+
if (isData(item)) result = snip(resolveData(this, item), Void, "runtime");
|
|
439
|
+
else if (isLazy(item) || isSlot(item)) result = this.resolve(this.unwrap(item));
|
|
440
|
+
else if (isSelfResolvable(item)) result = item[$resolve](this);
|
|
441
|
+
else if (hasTinyestMetadata(item)) {
|
|
442
|
+
const shellless = this.#namespaceInternal.shelllessRepo.get(item, void 0);
|
|
443
|
+
if (!shellless) throw new Error(`Couldn't resolve ${item.name}. Make sure it's a function that accepts no arguments, or call it from another TypeGPU function.`);
|
|
444
|
+
return this.withResetIndentLevel(() => this.resolve(shellless));
|
|
445
|
+
} else throw new TypeError(`Unresolvable internal value: ${safeStringify(item)}`);
|
|
446
|
+
const slotToValueMap = /* @__PURE__ */ new Map();
|
|
447
|
+
for (const usedSlot of this._itemStateStack.topItem.usedSlots) slotToValueMap.set(usedSlot, this._itemStateStack.readSlot(usedSlot));
|
|
448
|
+
instances.push({
|
|
449
|
+
slotToValueMap,
|
|
450
|
+
result
|
|
451
|
+
});
|
|
452
|
+
this.#namespaceInternal.memoizedResolves.set(item, instances);
|
|
453
|
+
return result;
|
|
454
|
+
} catch (err) {
|
|
455
|
+
if (err instanceof ResolutionError) throw err.appendToTrace(item);
|
|
456
|
+
throw new ResolutionError(err, [item]);
|
|
457
|
+
} finally {
|
|
458
|
+
this._itemStateStack.pop("item");
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
resolve(item, schema) {
|
|
462
|
+
if (isTgpuFn(item) || hasTinyestMetadata(item)) {
|
|
463
|
+
if (this.#currentlyResolvedItems.has(item) && !this.#namespaceInternal.memoizedResolves.has(item)) throw new Error(`Recursive function ${item} detected. Recursion is not allowed on the GPU.`);
|
|
464
|
+
this.#currentlyResolvedItems.add(item);
|
|
465
|
+
}
|
|
466
|
+
if (isProviding(item)) return this.withRenamed(item[$providing].inner, getName(item), () => this.withSlots(item[$providing].pairs, () => this.resolve(item[$providing].inner, schema)));
|
|
467
|
+
if (isMarkedInternal(item) || hasTinyestMetadata(item)) {
|
|
468
|
+
if (this._itemStateStack.itemDepth === 0) try {
|
|
469
|
+
this.pushMode(new CodegenState());
|
|
470
|
+
const result = provideCtx(this, () => this._getOrInstantiate(item));
|
|
471
|
+
return snip(`${[...this._declarations].join("\n\n")}${result.value}`, Void, "runtime");
|
|
472
|
+
} finally {
|
|
473
|
+
this.popMode("codegen");
|
|
474
|
+
}
|
|
475
|
+
return this._getOrInstantiate(item);
|
|
476
|
+
}
|
|
477
|
+
if (typeof item === "number") {
|
|
478
|
+
const realSchema = schema ?? numericLiteralToSnippet(item).dataType;
|
|
479
|
+
invariant(realSchema !== UnknownData, "Schema has to be known for resolving numbers");
|
|
480
|
+
if (realSchema.type === "abstractInt") return snip(`${item}`, realSchema, "constant");
|
|
481
|
+
if (realSchema.type === "u32") return snip(`${item}u`, realSchema, "constant");
|
|
482
|
+
if (realSchema.type === "i32") return snip(`${item}i`, realSchema, "constant");
|
|
483
|
+
const exp = item.toExponential();
|
|
484
|
+
const decimal = realSchema.type === "abstractFloat" && Number.isInteger(item) ? `${item}.` : `${item}`;
|
|
485
|
+
const base = exp.length < decimal.length ? exp : decimal;
|
|
486
|
+
if (realSchema.type === "f32") return snip(`${base}f`, realSchema, "constant");
|
|
487
|
+
if (realSchema.type === "f16") return snip(`${base}h`, realSchema, "constant");
|
|
488
|
+
return snip(base, realSchema, "constant");
|
|
489
|
+
}
|
|
490
|
+
if (typeof item === "boolean") return snip(item ? "true" : "false", bool, "constant");
|
|
491
|
+
if (typeof item === "string") return snip(item, Void, "runtime");
|
|
492
|
+
if (schema && isWgslArray(schema)) {
|
|
493
|
+
if (!Array.isArray(item)) throw new WgslTypeError(`Cannot coerce ${item} into value of type '${schema}'`);
|
|
494
|
+
if (schema.elementCount !== item.length) throw new WgslTypeError(`Cannot create value of type '${schema}' from an array of length: ${item.length}`);
|
|
495
|
+
return snip(stitch`array<${this.resolve(schema.elementType)}, ${schema.elementCount}>(${item.map((element) => snip(element, schema.elementType, "runtime"))})`, schema, "runtime");
|
|
496
|
+
}
|
|
497
|
+
if (Array.isArray(item)) return snip(stitch`array(${item.map((element) => this.resolve(element))})`, UnknownData, "runtime");
|
|
498
|
+
if (schema && isWgslStruct(schema)) return snip(stitch`${this.resolve(schema)}(${Object.entries(schema.propTypes).map(([key, propType]) => snip(item[key], propType, "runtime"))})`, schema, "runtime");
|
|
499
|
+
throw new WgslTypeError(`Value ${item} (as json: ${safeStringify(item)}) is not resolvable${schema ? ` to type ${safeStringify(schema)}` : ""}`);
|
|
500
|
+
}
|
|
501
|
+
pushMode(mode) {
|
|
502
|
+
this.#modeStack.push(mode);
|
|
503
|
+
}
|
|
504
|
+
popMode(expected) {
|
|
505
|
+
const mode = this.#modeStack.pop();
|
|
506
|
+
if (expected !== void 0) invariant(mode?.type === expected, "Unexpected mode");
|
|
507
|
+
}
|
|
508
|
+
get mode() {
|
|
509
|
+
return this.#modeStack[this.#modeStack.length - 1] ?? topLevelState;
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
function resolve(item, options) {
|
|
513
|
+
const ctx = new ResolutionCtxImpl(options);
|
|
514
|
+
let code = (options.config ? ctx.withSlots(options.config(new ConfigurableImpl([])).bindings, () => ctx.resolve(item)) : ctx.resolve(item)).value;
|
|
515
|
+
const memoMap = ctx.bindGroupLayoutsToPlaceholderMap;
|
|
516
|
+
const usedBindGroupLayouts = [];
|
|
517
|
+
const automaticIds = naturalsExcept(new Set([...memoMap.keys()].map((layout) => layout.index).filter((v) => v !== void 0)));
|
|
518
|
+
const layoutEntries = ctx.fixedBindings.map((binding, idx) => [String(idx), binding.layoutEntry]);
|
|
519
|
+
const createCatchallGroup = () => {
|
|
520
|
+
const catchallIdx = automaticIds.next().value;
|
|
521
|
+
const catchallLayout = bindGroupLayout(Object.fromEntries(layoutEntries));
|
|
522
|
+
usedBindGroupLayouts[catchallIdx] = catchallLayout;
|
|
523
|
+
code = code.replaceAll(CATCHALL_BIND_GROUP_IDX_MARKER, String(catchallIdx));
|
|
524
|
+
return [catchallIdx, new TgpuBindGroupImpl(catchallLayout, Object.fromEntries(ctx.fixedBindings.map((binding, idx) => [String(idx), binding.resource])))];
|
|
525
|
+
};
|
|
526
|
+
const catchall = layoutEntries.length > 0 ? createCatchallGroup() : void 0;
|
|
527
|
+
for (const [layout, placeholder] of memoMap.entries()) {
|
|
528
|
+
const idx = layout.index ?? automaticIds.next().value;
|
|
529
|
+
usedBindGroupLayouts[idx] = layout;
|
|
530
|
+
code = code.replaceAll(placeholder, String(idx));
|
|
531
|
+
}
|
|
532
|
+
if (options.enableExtensions && options.enableExtensions.length > 0) code = `${options.enableExtensions.map((ext) => `enable ${ext};`).join("\n")}\n\n${code}`;
|
|
533
|
+
return {
|
|
534
|
+
code,
|
|
535
|
+
usedBindGroupLayouts,
|
|
536
|
+
catchall,
|
|
537
|
+
logResources: ctx.logResources
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function resolveFunctionHeader(ctx, args, returnType) {
|
|
541
|
+
const argList = args.map((arg) => `${arg.value}: ${ctx.resolve(arg.dataType).value}`).join(", ");
|
|
542
|
+
return returnType.type !== "void" ? `(${argList}) -> ${getAttributesString(returnType)}${ctx.resolve(returnType).value} ` : `(${argList}) `;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
//#endregion
|
|
546
|
+
export { ResolutionCtxImpl, resolve };
|
package/shared/env.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/shared/env.ts
|
|
2
|
+
/**
|
|
3
|
+
* This can be used to branch functionality between "dev" and "prod" modes, so that our
|
|
4
|
+
* library can omit doing unnecessary work once it's out in the wild
|
|
5
|
+
*
|
|
6
|
+
* Even though the value of this constant uses Node.js specific APIs, pretty much every
|
|
7
|
+
* bundler replaces the expression below with either `development` or `production`
|
|
8
|
+
*/
|
|
9
|
+
const DEV = process.env.NODE_ENV === "development";
|
|
10
|
+
const TEST = process.env.NODE_ENV === "test";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { DEV, TEST };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/shared/generators.ts
|
|
2
|
+
/**
|
|
3
|
+
* Yields values in the sequence 0,1,2..∞ except for the ones in the `excluded` set.
|
|
4
|
+
*/
|
|
5
|
+
function* naturalsExcept(excluded) {
|
|
6
|
+
let next = 0;
|
|
7
|
+
while (true) {
|
|
8
|
+
if (!excluded.has(next)) yield next;
|
|
9
|
+
next++;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { naturalsExcept };
|
package/shared/meta.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Block, FuncParameter } from "tinyest";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/meta.d.ts
|
|
4
|
+
interface MetaData {
|
|
5
|
+
v?: number;
|
|
6
|
+
name?: string | undefined;
|
|
7
|
+
ast?: {
|
|
8
|
+
params: FuncParameter[];
|
|
9
|
+
body: Block;
|
|
10
|
+
externalNames: string[];
|
|
11
|
+
} | undefined;
|
|
12
|
+
externals?: Record<string, unknown> | (() => Record<string, unknown>) | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Don't use or you WILL get fired from your job.
|
|
16
|
+
*
|
|
17
|
+
* The information that this type describes is additional
|
|
18
|
+
* properties that we add onto `globalThis`, used by tools
|
|
19
|
+
* like `unplugin-typegpu` or our test suite.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
type INTERNAL_GlobalExt = typeof globalThis & {
|
|
24
|
+
__TYPEGPU_VERSION__: string | undefined;
|
|
25
|
+
__TYPEGPU_META__: WeakMap<object, MetaData>;
|
|
26
|
+
__TYPEGPU_AUTONAME__: <T>(exp: T, label: string) => T;
|
|
27
|
+
__TYPEGPU_MEASURE_PERF__?: boolean | undefined;
|
|
28
|
+
__TYPEGPU_PERF_RECORDS__?: Map<string, unknown[]> | undefined;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Can be assigned a name. Not to be confused with just having a name.
|
|
32
|
+
* The `$name` function should use `setName` to rename the object itself,
|
|
33
|
+
* even if `$getNameForward` symbol is present.
|
|
34
|
+
*/
|
|
35
|
+
interface TgpuNamable {
|
|
36
|
+
$name(label: string): this;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { INTERNAL_GlobalExt, TgpuNamable };
|
package/shared/meta.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { version } from "../package.js";
|
|
2
|
+
import { DEV, TEST } from "./env.js";
|
|
3
|
+
import { $getNameForward, isMarkedInternal } from "./symbols.js";
|
|
4
|
+
|
|
5
|
+
//#region src/shared/meta.ts
|
|
6
|
+
const globalWithMeta = globalThis;
|
|
7
|
+
if (globalWithMeta.__TYPEGPU_VERSION__ !== void 0) console.warn(`Found duplicate TypeGPU version. First was ${globalWithMeta.__TYPEGPU_VERSION__}, this one is ${version}. This may cause unexpected behavior.`);
|
|
8
|
+
globalWithMeta.__TYPEGPU_VERSION__ = version;
|
|
9
|
+
globalWithMeta.__TYPEGPU_AUTONAME__ = (exp, label) => isNamable(exp) && isMarkedInternal(exp) && !getName(exp) ? exp.$name(label) : exp;
|
|
10
|
+
/**
|
|
11
|
+
* Performance measurements are only enabled in dev & test environments for now
|
|
12
|
+
*/
|
|
13
|
+
const PERF = (DEV || TEST) && {
|
|
14
|
+
get enabled() {
|
|
15
|
+
return !!globalWithMeta.__TYPEGPU_MEASURE_PERF__;
|
|
16
|
+
},
|
|
17
|
+
record(name, data) {
|
|
18
|
+
const records = globalWithMeta.__TYPEGPU_PERF_RECORDS__ ??= /* @__PURE__ */ new Map();
|
|
19
|
+
let entries = records.get(name);
|
|
20
|
+
if (!entries) {
|
|
21
|
+
entries = [];
|
|
22
|
+
records.set(name, entries);
|
|
23
|
+
}
|
|
24
|
+
entries.push(data);
|
|
25
|
+
}
|
|
26
|
+
} || void 0;
|
|
27
|
+
function isForwarded(value) {
|
|
28
|
+
return !!value?.[$getNameForward];
|
|
29
|
+
}
|
|
30
|
+
function getName(definition) {
|
|
31
|
+
if (isForwarded(definition)) return getName(definition[$getNameForward]);
|
|
32
|
+
return getMetaData(definition)?.name;
|
|
33
|
+
}
|
|
34
|
+
function setName(definition, name) {
|
|
35
|
+
if (isForwarded(definition)) {
|
|
36
|
+
setName(definition[$getNameForward], name);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
setMetaData(definition, { name });
|
|
40
|
+
}
|
|
41
|
+
function isNamable(value) {
|
|
42
|
+
return !!value?.$name;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* AST's are given to functions with a 'use gpu' directive, which this function checks for.
|
|
46
|
+
*/
|
|
47
|
+
function hasTinyestMetadata(value) {
|
|
48
|
+
return !!getMetaData(value)?.ast;
|
|
49
|
+
}
|
|
50
|
+
function getMetaData(definition) {
|
|
51
|
+
return globalWithMeta.__TYPEGPU_META__.get(definition);
|
|
52
|
+
}
|
|
53
|
+
function setMetaData(definition, metaData) {
|
|
54
|
+
globalWithMeta.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap();
|
|
55
|
+
const map = globalWithMeta.__TYPEGPU_META__;
|
|
56
|
+
map.set(definition, {
|
|
57
|
+
...map.get(definition),
|
|
58
|
+
...metaData
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { PERF, getMetaData, getName, hasTinyestMetadata, isNamable, setName };
|