typegpu 0.11.2 → 0.11.4
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/README.md +1 -1
- package/core/buffer/buffer.js +17 -53
- 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.d.ts +1 -1
- package/core/function/tgpuFragmentFn.js +1 -1
- package/core/function/tgpuVertexFn.js +1 -1
- package/core/pipeline/computePipeline.d.ts +1 -1
- package/core/root/init.d.ts +1 -0
- package/core/root/init.js +6 -0
- package/core/root/rootTypes.d.ts +21 -15
- package/core/slot/accessor.js +1 -1
- package/data/dataIO.d.ts +11 -0
- package/data/dataIO.js +45 -1
- package/data/dataTypes.js +2 -11
- package/data/index.d.ts +3 -3
- package/data/numeric.js +16 -14
- package/data/partialIO.d.ts +8 -0
- package/data/partialIO.js +6 -1
- package/data/snippet.d.ts +1 -6
- package/data/wgslTypes.d.ts +2 -0
- package/index.d.ts +3 -1
- package/index.js +3 -1
- package/indexNamedExports.d.ts +2 -0
- package/package.js +1 -1
- package/package.json +1 -1
- package/resolutionCtx.js +82 -86
- package/shared/stringify.js +1 -0
- package/shared/tseynit.js +90 -0
- package/tgsl/accessIndex.js +4 -3
- package/tgsl/accessProp.js +7 -2
- package/tgsl/consoleLog/deserializers.js +1 -1
- package/tgsl/consoleLog/logGenerator.js +16 -14
- package/tgsl/consoleLog/types.d.ts +4 -5
- package/tgsl/conversion.js +15 -5
- package/tgsl/forOfUtils.js +14 -6
- package/tgsl/generationHelpers.d.ts +2 -1
- package/tgsl/generationHelpers.js +1 -4
- package/tgsl/jsPolyfills.d.ts +25 -0
- package/tgsl/jsPolyfills.js +44 -0
- 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 +64 -59
- package/types.d.ts +11 -6
- package/tgsl/consoleLog/types.js +0 -12
- package/tgsl/math.js +0 -45
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 };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BaseData } from "./wgslTypes.js";
|
|
2
|
+
import { InferPatch } from "../shared/repr.js";
|
|
3
|
+
|
|
4
|
+
//#region src/data/partialIO.d.ts
|
|
5
|
+
|
|
6
|
+
declare function patchArrayBuffer<T extends BaseData>(buffer: ArrayBuffer, schema: T, data: InferPatch<T>): void;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { patchArrayBuffer };
|
package/data/partialIO.js
CHANGED
|
@@ -110,6 +110,11 @@ function getPatchInstructions(schema, data, targetBuffer) {
|
|
|
110
110
|
});
|
|
111
111
|
return instructions;
|
|
112
112
|
}
|
|
113
|
+
function patchArrayBuffer(buffer, schema, data) {
|
|
114
|
+
const instructions = getPatchInstructions(schema, data, buffer);
|
|
115
|
+
const mappedView = new Uint8Array(buffer);
|
|
116
|
+
for (const { data: data$1, gpuOffset } of instructions) mappedView.set(data$1, gpuOffset);
|
|
117
|
+
}
|
|
113
118
|
|
|
114
119
|
//#endregion
|
|
115
|
-
export { convertPartialToPatch, getPatchInstructions };
|
|
120
|
+
export { convertPartialToPatch, getPatchInstructions, patchArrayBuffer };
|
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/index.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ import { index_d_exports as index_d_exports$2 } from "./std/index.js";
|
|
|
38
38
|
import { index_d_exports } from "./common/index.js";
|
|
39
39
|
import { MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError } from "./errors.js";
|
|
40
40
|
import { WgslGenerator } from "./tgsl/wgslGenerator.js";
|
|
41
|
+
import { readFromArrayBuffer, writeToArrayBuffer } from "./data/dataIO.js";
|
|
42
|
+
import { patchArrayBuffer } from "./data/partialIO.js";
|
|
41
43
|
import { TgpuRenderPipelineDescriptor } from "./indexNamedExports.js";
|
|
42
44
|
|
|
43
45
|
//#region src/index.d.ts
|
|
@@ -68,4 +70,4 @@ declare const tgpu: {
|
|
|
68
70
|
'~unstable': typeof tgpuUnstable_d_exports;
|
|
69
71
|
};
|
|
70
72
|
//#endregion
|
|
71
|
-
export { AutoFragmentIn, AutoFragmentOut, _AutoVertexIn as AutoVertexIn, AutoVertexOut, BindLayoutEntry, ColorAttachment, Configurable, Eventual, ExtractBindGroupInputFromLayout, INTERNAL_GlobalExt, IndexFlag, InitFromDeviceOptions, InitOptions, LayoutEntryToInput, MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, Namespace, NotUniformError, RawCodeSnippetOrigin, RenderFlag, ResolutionError, SampledFlag, ShaderGenerator, Storage, StorageFlag, TextureProps, TgpuAccessor, TgpuBindGroup, TgpuBindGroupLayout, TgpuBuffer, TgpuBufferMutable, TgpuBufferReadonly, TgpuBufferUniform, TgpuComparisonSampler, TgpuComptime, TgpuComputeFn, TgpuComputeFnShell, TgpuComputePipeline, TgpuConst, TgpuDeclare, TgpuFixedComparisonSampler, TgpuFixedSampler, TgpuFn, TgpuFnShell, TgpuFragmentFn, TgpuFragmentFnShell, TgpuGenericFn, TgpuGuardedComputePipeline, TgpuLayoutComparisonSampler, TgpuLayoutEntry, TgpuLayoutExternalTexture, TgpuLayoutSampler, TgpuLayoutStorage, TgpuLayoutTexture, TgpuLayoutUniform, TgpuLazy, TgpuMutable, TgpuMutableAccessor, TgpuPrimitiveState, TgpuQuerySet, TgpuRawCodeSnippet, TgpuReadonly, TgpuRenderPipeline, TgpuRenderPipelineDescriptor, TgpuRoot, TgpuSampler, TgpuSlot, TgpuTexture, TgpuTextureView, TgpuUniform, TgpuVar, TgpuVertexFn, TgpuVertexFnShell, TgpuVertexLayout, Uniform, UniformFlag, ValidUsagesFor, ValidateBufferSchema, ValidateStorageSchema, ValidateUniformSchema, VariableScope, Vertex, VertexFlag, WgslGenerator, WithBinding, WithCompute, WithFragment, WithVertex, Withable, index_d_exports as common, index_d_exports$1 as d, tgpu as default, tgpu, isAccessor, isBuffer, isBufferShorthand, isComparisonSampler, isLazy, isMutableAccessor, isSampler, isSlot, isTexture, isTgpuComputeFn, isTgpuFn, isTgpuFragmentFn, isTgpuVertexFn, isUsableAsRender, isUsableAsSampled, isUsableAsStorage, isUsableAsUniform, isUsableAsVertex, isVariable, index_d_exports$2 as std };
|
|
73
|
+
export { AutoFragmentIn, AutoFragmentOut, _AutoVertexIn as AutoVertexIn, AutoVertexOut, BindLayoutEntry, ColorAttachment, Configurable, Eventual, ExtractBindGroupInputFromLayout, INTERNAL_GlobalExt, IndexFlag, InitFromDeviceOptions, InitOptions, LayoutEntryToInput, MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, Namespace, NotUniformError, RawCodeSnippetOrigin, RenderFlag, ResolutionError, SampledFlag, ShaderGenerator, Storage, StorageFlag, TextureProps, TgpuAccessor, TgpuBindGroup, TgpuBindGroupLayout, TgpuBuffer, TgpuBufferMutable, TgpuBufferReadonly, TgpuBufferUniform, TgpuComparisonSampler, TgpuComptime, TgpuComputeFn, TgpuComputeFnShell, TgpuComputePipeline, TgpuConst, TgpuDeclare, TgpuFixedComparisonSampler, TgpuFixedSampler, TgpuFn, TgpuFnShell, TgpuFragmentFn, TgpuFragmentFnShell, TgpuGenericFn, TgpuGuardedComputePipeline, TgpuLayoutComparisonSampler, TgpuLayoutEntry, TgpuLayoutExternalTexture, TgpuLayoutSampler, TgpuLayoutStorage, TgpuLayoutTexture, TgpuLayoutUniform, TgpuLazy, TgpuMutable, TgpuMutableAccessor, TgpuPrimitiveState, TgpuQuerySet, TgpuRawCodeSnippet, TgpuReadonly, TgpuRenderPipeline, TgpuRenderPipelineDescriptor, TgpuRoot, TgpuSampler, TgpuSlot, TgpuTexture, TgpuTextureView, TgpuUniform, TgpuVar, TgpuVertexFn, TgpuVertexFnShell, TgpuVertexLayout, Uniform, UniformFlag, ValidUsagesFor, ValidateBufferSchema, ValidateStorageSchema, ValidateUniformSchema, VariableScope, Vertex, VertexFlag, WgslGenerator, WithBinding, WithCompute, WithFragment, WithVertex, Withable, index_d_exports as common, index_d_exports$1 as d, tgpu as default, tgpu, isAccessor, isBuffer, isBufferShorthand, isComparisonSampler, isLazy, isMutableAccessor, isSampler, isSlot, isTexture, isTgpuComputeFn, isTgpuFn, isTgpuFragmentFn, isTgpuVertexFn, isUsableAsRender, isUsableAsSampled, isUsableAsStorage, isUsableAsUniform, isUsableAsVertex, isVariable, patchArrayBuffer, readFromArrayBuffer, index_d_exports$2 as std, writeToArrayBuffer };
|
package/index.js
CHANGED
|
@@ -2,6 +2,8 @@ import { MissingBindGroupsError, MissingLinksError, MissingSlotValueError, Missi
|
|
|
2
2
|
import { isAccessor, isLazy, isMutableAccessor, isSlot } from "./core/slot/slotTypes.js";
|
|
3
3
|
import { shaderGenerator_members_exports } from "./tgsl/shaderGenerator_members.js";
|
|
4
4
|
import { isTgpuFn } from "./core/function/tgpuFn.js";
|
|
5
|
+
import { readFromArrayBuffer, writeToArrayBuffer } from "./data/dataIO.js";
|
|
6
|
+
import { patchArrayBuffer } from "./data/partialIO.js";
|
|
5
7
|
import { isUsableAsStorage } from "./extension.js";
|
|
6
8
|
import { isUsableAsUniform } from "./core/buffer/bufferUsage.js";
|
|
7
9
|
import { isBuffer, isUsableAsVertex } from "./core/buffer/buffer.js";
|
|
@@ -23,4 +25,4 @@ import { common_exports } from "./common/index.js";
|
|
|
23
25
|
var src_default = tgpu_exports;
|
|
24
26
|
|
|
25
27
|
//#endregion
|
|
26
|
-
export { MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, shaderGenerator_members_exports as ShaderGenerator, WgslGenerator, common_exports as common, data_exports as d, src_default as default, isAccessor, isBuffer, isBufferShorthand, isComparisonSampler, isLazy, isMutableAccessor, isSampler, isSlot, isTexture, isTgpuComputeFn, isTgpuFn, isTgpuFragmentFn, isTgpuVertexFn, isUsableAsRender, isUsableAsSampled, isUsableAsStorage, isUsableAsUniform, isUsableAsVertex, isVariable, std_exports as std, tgpu_exports as tgpu };
|
|
28
|
+
export { MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError, shaderGenerator_members_exports as ShaderGenerator, WgslGenerator, common_exports as common, data_exports as d, src_default as default, isAccessor, isBuffer, isBufferShorthand, isComparisonSampler, isLazy, isMutableAccessor, isSampler, isSlot, isTexture, isTgpuComputeFn, isTgpuFn, isTgpuFragmentFn, isTgpuVertexFn, isUsableAsRender, isUsableAsSampled, isUsableAsStorage, isUsableAsUniform, isUsableAsVertex, isVariable, patchArrayBuffer, readFromArrayBuffer, std_exports as std, tgpu_exports as tgpu, writeToArrayBuffer };
|
package/indexNamedExports.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { index_d_exports as index_d_exports$1 } from "./std/index.js";
|
|
|
32
32
|
import { index_d_exports as index_d_exports$2 } from "./common/index.js";
|
|
33
33
|
import { MissingBindGroupsError, MissingLinksError, MissingSlotValueError, MissingVertexBuffersError, NotUniformError, ResolutionError } from "./errors.js";
|
|
34
34
|
import { WgslGenerator } from "./tgsl/wgslGenerator.js";
|
|
35
|
+
import { readFromArrayBuffer, writeToArrayBuffer } from "./data/dataIO.js";
|
|
36
|
+
import { patchArrayBuffer } from "./data/partialIO.js";
|
|
35
37
|
|
|
36
38
|
//#region src/indexNamedExports.d.ts
|
|
37
39
|
|
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 {
|
|
@@ -556,9 +560,8 @@ var ResolutionCtxImpl = class {
|
|
|
556
560
|
if (schema.elementCount !== item.length) throw new WgslTypeError(`Cannot create value of type '${schema}' from an array of length: ${item.length}`);
|
|
557
561
|
return snip(stitch`array<${this.resolve(schema.elementType)}, ${schema.elementCount}>(${item.map((element) => snip(element, schema.elementType, "runtime"))})`, schema, "runtime");
|
|
558
562
|
}
|
|
559
|
-
if (Array.isArray(item)) return snip(stitch`array(${item.map((element) => this.resolve(element))})`, UnknownData, "runtime");
|
|
560
563
|
if (schema && isWgslStruct(schema)) return snip(stitch`${this.resolve(schema)}(${Object.entries(schema.propTypes).map(([key, propType]) => snip(item[key], propType, "runtime"))})`, schema, "runtime");
|
|
561
|
-
throw new WgslTypeError(`Value ${
|
|
564
|
+
throw new WgslTypeError(`Value ${safeStringify(item)} is not resolvable${schema ? ` to type ${safeStringify(schema)}` : ""}`);
|
|
562
565
|
}
|
|
563
566
|
resolveSnippet(snippet) {
|
|
564
567
|
return snip(this.resolve(snippet.value, snippet.dataType).value, snippet.dataType, snippet.origin);
|
|
@@ -602,13 +605,6 @@ function resolve(item, options) {
|
|
|
602
605
|
logResources: ctx.logResources
|
|
603
606
|
};
|
|
604
607
|
}
|
|
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
608
|
|
|
613
609
|
//#endregion
|
|
614
610
|
export { ResolutionCtxImpl, resolve };
|
package/shared/stringify.js
CHANGED
|
@@ -2,6 +2,7 @@ import { isMatInstance, isVecInstance } from "../data/wgslTypes.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/shared/stringify.ts
|
|
4
4
|
function safeStringify(item) {
|
|
5
|
+
if (Array.isArray(item)) return `[${item.map(safeStringify).join(", ")}]`;
|
|
5
6
|
const asString = String(item);
|
|
6
7
|
if (asString !== "[object Object]") return asString;
|
|
7
8
|
try {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as tinyest from "tinyest";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/tseynit.ts
|
|
4
|
+
const { NodeTypeCatalog: NODE } = tinyest;
|
|
5
|
+
function stringifyNode(node) {
|
|
6
|
+
if (isExpression(node)) return stringifyExpression(node, "");
|
|
7
|
+
return stringifyStatement(node, "");
|
|
8
|
+
}
|
|
9
|
+
function stringifyStatement(node, ident) {
|
|
10
|
+
if (isExpression(node)) return `${ident}${stringifyExpression(node, ident)};`;
|
|
11
|
+
if (node[0] === NODE.block) return `{\n${node[1].map((n) => stringifyStatement(n, ident + " ")).join("\n")}\n${ident}}`;
|
|
12
|
+
if (node[0] === NODE.return) return `${ident}return${node[1] === void 0 ? "" : ` ${stringifyExpression(node[1], "")}`};`;
|
|
13
|
+
if (node[0] === NODE.if) {
|
|
14
|
+
const base = `${ident}if (${stringifyExpression(node[1], ident)}) ${stringifyStatement(node[2], ident)}`;
|
|
15
|
+
if (node[3] !== void 0) return `${base} else ${stringifyStatement(node[3], ident)}`;
|
|
16
|
+
return base;
|
|
17
|
+
}
|
|
18
|
+
if (node[0] === NODE.let) {
|
|
19
|
+
if (node[2] !== void 0) return `${ident}let ${node[1]} = ${stringifyExpression(node[2], ident)};`;
|
|
20
|
+
return `${ident}let ${node[1]};`;
|
|
21
|
+
}
|
|
22
|
+
if (node[0] === NODE.const) {
|
|
23
|
+
if (node[2] !== void 0) return `${ident}const ${node[1]} = ${stringifyExpression(node[2], ident)};`;
|
|
24
|
+
return `${ident}const ${node[1]};`;
|
|
25
|
+
}
|
|
26
|
+
if (node[0] === NODE.for) {
|
|
27
|
+
const init = node[1] ? stringifyStatement(node[1], "") : ";";
|
|
28
|
+
const cond = node[2] ? stringifyExpression(node[2], ident) : "";
|
|
29
|
+
const update = node[3] ? stringifyStatement(node[3], "") : "";
|
|
30
|
+
const body = stringifyStatement(node[4], ident);
|
|
31
|
+
return `${ident}for (${init} ${cond}; ${update.slice(0, -1)}) ${body}`;
|
|
32
|
+
}
|
|
33
|
+
if (node[0] === NODE.while) return `${ident}while (${stringifyExpression(node[1], ident)}) ${stringifyStatement(node[2], ident)}`;
|
|
34
|
+
if (node[0] === NODE.continue) return `${ident}continue;`;
|
|
35
|
+
if (node[0] === NODE.break) return `${ident}break;`;
|
|
36
|
+
if (node[0] === NODE.forOf) return `${ident}for (${node[1][0] === NODE.const ? "const" : "let"} ${node[1][1]} of ${stringifyExpression(node[2], ident)}) ${stringifyStatement(node[3], ident)}`;
|
|
37
|
+
assertExhaustive(node);
|
|
38
|
+
}
|
|
39
|
+
function stringifyExpression(node, ident) {
|
|
40
|
+
if (typeof node === "string") return node;
|
|
41
|
+
if (typeof node === "boolean") return `${node}`;
|
|
42
|
+
if (node[0] === NODE.numericLiteral) return node[1];
|
|
43
|
+
if (node[0] === NODE.stringLiteral) return JSON.stringify(node[1]);
|
|
44
|
+
if (node[0] === NODE.arrayExpr) return `[${node[1].map((n) => stringifyExpression(n, ident)).join(", ")}]`;
|
|
45
|
+
if (node[0] === NODE.binaryExpr) return `${wrapIfComplex(node[1], ident)} ${node[2]} ${wrapIfComplex(node[3], ident)}`;
|
|
46
|
+
if (node[0] === NODE.assignmentExpr) return `${stringifyExpression(node[1], ident)} ${node[2]} ${stringifyExpression(node[3], ident)}`;
|
|
47
|
+
if (node[0] === NODE.logicalExpr) return `${wrapIfComplex(node[1], ident)} ${node[2]} ${wrapIfComplex(node[3], ident)}`;
|
|
48
|
+
if (node[0] === NODE.unaryExpr) {
|
|
49
|
+
const sep = node[1].length > 1 ? " " : "";
|
|
50
|
+
return `${node[1]}${sep}${wrapIfComplex(node[2], ident)}`;
|
|
51
|
+
}
|
|
52
|
+
if (node[0] === NODE.call) return `${wrapIfComplex(node[1], ident)}(${node[2].map((n) => stringifyExpression(n, ident)).join(", ")})`;
|
|
53
|
+
if (node[0] === NODE.memberAccess) {
|
|
54
|
+
if (Array.isArray(node[1]) && node[1][0] === NODE.numericLiteral) return `(${stringifyExpression(node[1], ident)}).${node[2]}`;
|
|
55
|
+
return `${wrapIfComplex(node[1], ident)}.${node[2]}`;
|
|
56
|
+
}
|
|
57
|
+
if (node[0] === NODE.indexAccess) return `${wrapIfComplex(node[1], ident)}[${stringifyExpression(node[2], ident)}]`;
|
|
58
|
+
if (node[0] === NODE.preUpdate) return `${node[1]}${wrapIfComplex(node[2], ident)}`;
|
|
59
|
+
if (node[0] === NODE.postUpdate) return `${wrapIfComplex(node[2], ident)}${node[1]}`;
|
|
60
|
+
if (node[0] === NODE.objectExpr) return `{ ${Object.entries(node[1]).map(([key, val]) => `${key}: ${stringifyExpression(val, ident)}`).join(", ")} }`;
|
|
61
|
+
if (node[0] === NODE.conditionalExpr) return `${wrapIfComplex(node[1], ident)} ? ${wrapIfComplex(node[2], ident)} : ${wrapIfComplex(node[3], ident)}`;
|
|
62
|
+
assertExhaustive(node);
|
|
63
|
+
}
|
|
64
|
+
function assertExhaustive(value) {
|
|
65
|
+
throw new Error(`'${JSON.stringify(value)}' was not handled by the stringify function.`);
|
|
66
|
+
}
|
|
67
|
+
function isExpression(node) {
|
|
68
|
+
if (typeof node === "string" || typeof node === "boolean" || node[0] === NODE.numericLiteral || node[0] === NODE.stringLiteral || node[0] === NODE.arrayExpr || node[0] === NODE.binaryExpr || node[0] === NODE.assignmentExpr || node[0] === NODE.logicalExpr || node[0] === NODE.unaryExpr || node[0] === NODE.call || node[0] === NODE.memberAccess || node[0] === NODE.indexAccess || node[0] === NODE.preUpdate || node[0] === NODE.postUpdate || node[0] === NODE.objectExpr || node[0] === NODE.conditionalExpr) return true;
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const SIMPLE_NODES = [
|
|
72
|
+
NODE.memberAccess,
|
|
73
|
+
NODE.indexAccess,
|
|
74
|
+
NODE.call,
|
|
75
|
+
NODE.arrayExpr,
|
|
76
|
+
NODE.stringLiteral,
|
|
77
|
+
NODE.numericLiteral
|
|
78
|
+
];
|
|
79
|
+
/**
|
|
80
|
+
* Stringifies expression, and wraps it in parentheses if they cannot be trivially omitted
|
|
81
|
+
*/
|
|
82
|
+
function wrapIfComplex(node, ident) {
|
|
83
|
+
const s = stringifyExpression(node, ident);
|
|
84
|
+
if (typeof node === "string" || typeof node === "boolean") return s;
|
|
85
|
+
if (SIMPLE_NODES.includes(node[0])) return s;
|
|
86
|
+
return `(${s})`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//#endregion
|
|
90
|
+
export { stringifyNode };
|
package/tgsl/accessIndex.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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";
|
|
6
6
|
import { derefSnippet } from "../data/ref.js";
|
|
7
|
-
import { coerceToSnippet } from "./generationHelpers.js";
|
|
7
|
+
import { ArrayExpression, coerceToSnippet } from "./generationHelpers.js";
|
|
8
8
|
import { vec2f, vec3f, vec4f } from "../data/vector.js";
|
|
9
9
|
import { accessProp } from "./accessProp.js";
|
|
10
10
|
|
|
@@ -28,6 +28,7 @@ function accessIndex(target, indexArg) {
|
|
|
28
28
|
else if (!isTargetEphemeral && !isElementNatEph) origin = target.origin;
|
|
29
29
|
else if (isIndexConstant && target.origin === "constant") origin = "constant";
|
|
30
30
|
else origin = "runtime";
|
|
31
|
+
if (target.value instanceof ArrayExpression && isKnownAtComptime(index)) return target.value.elements[index.value];
|
|
31
32
|
return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, elementType, origin);
|
|
32
33
|
}
|
|
33
34
|
if (isVec(target.dataType)) return snip(isKnownAtComptime(target) && isKnownAtComptime(index) ? target.value[index.value] : stitch`${target}[${index}]`, target.dataType.primitive, target.origin === "constant" || target.origin === "constant-tgpu-const-ref" ? "constant" : "runtime");
|
|
@@ -37,7 +38,7 @@ function accessIndex(target, indexArg) {
|
|
|
37
38
|
return snip(stitch`${target.value.matrix}[${index}]`, propType, target.origin);
|
|
38
39
|
}
|
|
39
40
|
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)
|
|
41
|
+
if (isKnownAtComptime(target) && isKnownAtComptime(index)) return coerceToSnippet(target.value[index.value]);
|
|
41
42
|
if (isWgslStruct(target.dataType) && isKnownAtComptime(index) && typeof index.value === "string") return accessProp(target, index.value);
|
|
42
43
|
}
|
|
43
44
|
|
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;
|
|
@@ -103,7 +103,7 @@ function logDataFromGPU(resources) {
|
|
|
103
103
|
const { argTypes, op } = logIdToMeta.get(id);
|
|
104
104
|
const results = deserializeAndStringify(new Uint32Array(serializedData), argTypes);
|
|
105
105
|
if (results.length === 0) results.push("");
|
|
106
|
-
|
|
106
|
+
op.bind(console)(`%c${options.messagePrefix}%c ${results[0]}`, "background: #936ff5; color: white;", "color: inherit; background: none", ...results.slice(1));
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
109
|
indexBuffer.read().then((totalCalls) => {
|