typegpu 0.11.7 → 0.11.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/declare/tgpuDeclare.js +2 -2
- package/core/function/fnCore.js +6 -6
- package/core/rawCodeSnippet/tgpuRawCodeSnippet.js +2 -2
- package/core/resolve/externals.d.ts +1 -1
- package/core/resolve/externals.js +23 -9
- package/core/resolve/tgpuResolve.js +2 -2
- package/package.js +1 -1
- package/package.json +1 -1
- package/shared/normalizeMetadata.js +3 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $internal, $resolve } from "../../shared/symbols.js";
|
|
2
2
|
import { Void } from "../../data/wgslTypes.js";
|
|
3
3
|
import { snip } from "../../data/snippet.js";
|
|
4
|
-
import {
|
|
4
|
+
import { mergeExternals, replaceExternalsInWgsl } from "../resolve/externals.js";
|
|
5
5
|
|
|
6
6
|
//#region src/core/declare/tgpuDeclare.ts
|
|
7
7
|
/**
|
|
@@ -27,7 +27,7 @@ var TgpuDeclareImpl = class {
|
|
|
27
27
|
}
|
|
28
28
|
[$resolve](ctx) {
|
|
29
29
|
const externalMap = {};
|
|
30
|
-
for (const externals of this.#externalsToApply)
|
|
30
|
+
for (const externals of this.#externalsToApply) mergeExternals(externalMap, externals);
|
|
31
31
|
const replacedDeclaration = replaceExternalsInWgsl(ctx, externalMap, this.#declaration);
|
|
32
32
|
ctx.addDeclaration(replacedDeclaration);
|
|
33
33
|
return snip("", Void, "constant");
|
package/core/function/fnCore.js
CHANGED
|
@@ -5,7 +5,7 @@ import { undecorate } from "../../data/dataTypes.js";
|
|
|
5
5
|
import { snip } from "../../data/snippet.js";
|
|
6
6
|
import { getAttributesString } from "../../data/attributes.js";
|
|
7
7
|
import { validateIdentifier } from "../../nameUtils.js";
|
|
8
|
-
import {
|
|
8
|
+
import { mergeExternals, replaceExternalsInWgsl } from "../resolve/externals.js";
|
|
9
9
|
import { extractArgs } from "./extractArgs.js";
|
|
10
10
|
|
|
11
11
|
//#region src/core/function/fnCore.ts
|
|
@@ -28,7 +28,7 @@ function createFnCore(implementation, functionType, workgroupSize) {
|
|
|
28
28
|
if (functionType === "compute") attributes = `@compute @workgroup_size(${workgroupSize?.join(", ")}) `;
|
|
29
29
|
else if (functionType === "vertex") attributes = `@vertex `;
|
|
30
30
|
else if (functionType === "fragment") attributes = `@fragment `;
|
|
31
|
-
for (const externals of externalsToApply)
|
|
31
|
+
for (const externals of externalsToApply) mergeExternals(externalMap, externals);
|
|
32
32
|
const id = ctx.makeUniqueIdentifier(getName(this), "global");
|
|
33
33
|
if (typeof implementation === "string") {
|
|
34
34
|
if (!returnType) throw new Error("Explicit return type is required for string implementation");
|
|
@@ -37,7 +37,7 @@ function createFnCore(implementation, functionType, workgroupSize) {
|
|
|
37
37
|
const result = /* @__PURE__ */ validateIdentifier(arg.schemaKey);
|
|
38
38
|
if (!result.success) throw new Error(`Invalid argument name "${arg.schemaKey}"${result.error ? `: ${result.error}` : ""}`);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
mergeExternals(externalMap, { in: Object.fromEntries(entryInput.positionalArgs.map((a) => [a.schemaKey, a.schemaKey])) });
|
|
41
41
|
}
|
|
42
42
|
const replacedImpl = replaceExternalsInWgsl(ctx, externalMap, implementation);
|
|
43
43
|
let header = "";
|
|
@@ -64,12 +64,12 @@ function createFnCore(implementation, functionType, workgroupSize) {
|
|
|
64
64
|
return snip(id, returnType, "runtime");
|
|
65
65
|
}
|
|
66
66
|
const pluginData = getFunctionMetadata(implementation);
|
|
67
|
-
const pluginExternals = pluginData?.externals;
|
|
68
|
-
if (pluginExternals)
|
|
67
|
+
const pluginExternals = pluginData?.externals();
|
|
68
|
+
if (pluginExternals) mergeExternals(externalMap, Object.fromEntries(Object.entries(pluginExternals).filter(([name]) => !(name in externalMap))));
|
|
69
69
|
const ast = pluginData?.ast;
|
|
70
70
|
if (!ast) throw new Error("Missing metadata for tgpu.fn function body (either missing 'use gpu' directive, or misconfigured `unplugin-typegpu`)");
|
|
71
71
|
const maybeSecondArg = ast.params[1];
|
|
72
|
-
if (maybeSecondArg && maybeSecondArg.type === "i" && functionType !== "normal")
|
|
72
|
+
if (maybeSecondArg && maybeSecondArg.type === "i" && functionType !== "normal") mergeExternals(externalMap, { [maybeSecondArg.name]: undecorate(returnType) });
|
|
73
73
|
const { code, returnType: actualReturnType } = ctx.resolveFunction({
|
|
74
74
|
functionType,
|
|
75
75
|
name: id,
|
|
@@ -2,7 +2,7 @@ import { $gpuValueOf, $internal, $ownSnippet, $resolve } from "../../shared/symb
|
|
|
2
2
|
import { snip } from "../../data/snippet.js";
|
|
3
3
|
import { inCodegenMode } from "../../execMode.js";
|
|
4
4
|
import { valueProxyHandler } from "../valueProxyUtils.js";
|
|
5
|
-
import {
|
|
5
|
+
import { mergeExternals, replaceExternalsInWgsl } from "../resolve/externals.js";
|
|
6
6
|
|
|
7
7
|
//#region src/core/rawCodeSnippet/tgpuRawCodeSnippet.ts
|
|
8
8
|
/**
|
|
@@ -65,7 +65,7 @@ var TgpuRawCodeSnippetImpl = class {
|
|
|
65
65
|
}
|
|
66
66
|
[$resolve](ctx) {
|
|
67
67
|
const externalMap = {};
|
|
68
|
-
for (const externals of this.#externalsToApply)
|
|
68
|
+
for (const externals of this.#externalsToApply) mergeExternals(externalMap, externals);
|
|
69
69
|
return snip(replaceExternalsInWgsl(ctx, externalMap, this.#expression), this.dataType, this.origin);
|
|
70
70
|
}
|
|
71
71
|
toString() {
|
|
@@ -4,7 +4,7 @@ import "../../types.js";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A key-value mapping where keys represent identifiers within shader code,
|
|
7
|
-
* and values can be any type that can be resolved to a code string.
|
|
7
|
+
* and values can either be another ExternalMap, or be any type that can be resolved to a code string.
|
|
8
8
|
*/
|
|
9
9
|
type ExternalMap = Record<string, unknown>;
|
|
10
10
|
//#endregion
|
|
@@ -4,29 +4,43 @@ import { isLooseData } from "../../data/dataTypes.js";
|
|
|
4
4
|
import { isWgsl } from "../../types.js";
|
|
5
5
|
|
|
6
6
|
//#region src/core/resolve/externals.ts
|
|
7
|
+
function isResolvable(value) {
|
|
8
|
+
return isWgsl(value) || isLooseData(value) || hasTinyestMetadata(value);
|
|
9
|
+
}
|
|
7
10
|
/**
|
|
8
|
-
* Merges two external maps into one.
|
|
11
|
+
* Merges two external maps into one.
|
|
9
12
|
* If the external value is a namable object, it is given a name if it does not already have one.
|
|
10
13
|
* @param existing - The existing external map.
|
|
11
14
|
* @param newExternals - The new external map.
|
|
15
|
+
*
|
|
16
|
+
* NOTE:
|
|
17
|
+
* This function attempts to avoid accidental reference modification
|
|
18
|
+
* by performing a shallow copy before each modification,
|
|
19
|
+
* but it cannot avoid `existing` modification.
|
|
20
|
+
* Make sure that `existing` is created internally, instead of being passed in by users.
|
|
12
21
|
*/
|
|
13
|
-
function
|
|
22
|
+
function mergeExternals(existing, newExternals) {
|
|
14
23
|
for (const [key, value] of Object.entries(newExternals)) {
|
|
15
|
-
existing[key]
|
|
24
|
+
const existingValue = existing[key];
|
|
25
|
+
if (existingValue !== null && typeof existingValue === "object" && value !== null && typeof value === "object" && !isResolvable(existingValue) && !isResolvable(value)) {
|
|
26
|
+
const copiedValue = { ...existingValue };
|
|
27
|
+
mergeExternals(copiedValue, value);
|
|
28
|
+
existing[key] = copiedValue;
|
|
29
|
+
} else existing[key] = value;
|
|
16
30
|
if (value && (typeof value === "object" || typeof value === "function") && getName(value) === void 0) setName(value, key);
|
|
17
31
|
}
|
|
18
32
|
}
|
|
19
|
-
function addArgTypesToExternals(implementation, argTypes, applyExternals
|
|
33
|
+
function addArgTypesToExternals(implementation, argTypes, applyExternals) {
|
|
20
34
|
const argTypeNames = [...implementation.matchAll(/:\s*(?<arg>.*?)\s*[,)]/g)].map((found) => found ? found[1] : void 0);
|
|
21
|
-
applyExternals
|
|
35
|
+
applyExternals(Object.fromEntries(argTypes.flatMap((argType, i) => {
|
|
22
36
|
const argTypeName = argTypeNames ? argTypeNames[i] : void 0;
|
|
23
37
|
return isWgslStruct(argType) && argTypeName !== void 0 ? [[argTypeName, argType]] : [];
|
|
24
38
|
})));
|
|
25
39
|
}
|
|
26
|
-
function addReturnTypeToExternals(implementation, returnType, applyExternals
|
|
40
|
+
function addReturnTypeToExternals(implementation, returnType, applyExternals) {
|
|
27
41
|
const matched = implementation.match(/->\s(?<output>[\w\d_]+)\s{/);
|
|
28
42
|
const outputName = matched ? matched[1]?.trim() : void 0;
|
|
29
|
-
if (isWgslStruct(returnType) && outputName && !/\s/g.test(outputName)) applyExternals
|
|
43
|
+
if (isWgslStruct(returnType) && outputName && !/\s/g.test(outputName)) applyExternals({ [outputName]: returnType });
|
|
30
44
|
}
|
|
31
45
|
function identifierRegex(name) {
|
|
32
46
|
return new RegExp(`(?<![\\w\\$_.])${name.replaceAll(".", "\\.").replaceAll("$", "\\$")}(?![\\w\\$_])`, "g");
|
|
@@ -44,7 +58,7 @@ function replaceExternalsInWgsl(ctx, externalMap, wgsl) {
|
|
|
44
58
|
return Object.entries(externalMap).reduce((acc, [externalName, external]) => {
|
|
45
59
|
const externalRegex = identifierRegex(externalName);
|
|
46
60
|
if (wgsl && externalName !== "Out" && externalName !== "in" && !externalRegex.test(wgsl)) console.warn(`The external '${externalName}' wasn't used in the resolved template.`);
|
|
47
|
-
if (
|
|
61
|
+
if (isResolvable(external)) return acc.replaceAll(externalRegex, ctx.resolve(external).value);
|
|
48
62
|
if (external !== null && typeof external === "object") {
|
|
49
63
|
const foundProperties = [...wgsl.matchAll(new RegExp(`${externalName.replaceAll(".", "\\.").replaceAll("$", "\\$")}\\.(?<prop>.*?)(?![\\w\\$_])`, "g"))].map((found) => found[1]);
|
|
50
64
|
return [...new Set(foundProperties)].reduce((innerAcc, prop) => prop && prop in external ? replaceExternalsInWgsl(ctx, { [`${externalName}.${prop}`]: external[prop] }, innerAcc) : innerAcc, acc);
|
|
@@ -55,4 +69,4 @@ function replaceExternalsInWgsl(ctx, externalMap, wgsl) {
|
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
//#endregion
|
|
58
|
-
export { addArgTypesToExternals, addReturnTypeToExternals,
|
|
72
|
+
export { addArgTypesToExternals, addReturnTypeToExternals, mergeExternals, replaceExternalsInWgsl };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $internal, $resolve } from "../../shared/symbols.js";
|
|
2
2
|
import { Void } from "../../data/wgslTypes.js";
|
|
3
3
|
import { snip } from "../../data/snippet.js";
|
|
4
|
-
import {
|
|
4
|
+
import { mergeExternals, replaceExternalsInWgsl } from "./externals.js";
|
|
5
5
|
import { isBindGroupLayout } from "../../tgpuBindGroupLayout.js";
|
|
6
6
|
import { resolve } from "../../resolutionCtx.js";
|
|
7
7
|
import { isPipeline } from "../pipeline/typeGuards.js";
|
|
@@ -20,7 +20,7 @@ function resolveFromTemplate(options) {
|
|
|
20
20
|
const { template, externals, unstable_shaderGenerator: shaderGenerator, names = "strict", config, enableExtensions } = options;
|
|
21
21
|
if (!template) console.warn("Calling resolve with an empty template is deprecated and will soon return an empty string. Consider using the 'tgpu.resolve(resolvableArray, options)' API instead.");
|
|
22
22
|
const dependencies = {};
|
|
23
|
-
|
|
23
|
+
mergeExternals(dependencies, externals ?? {});
|
|
24
24
|
return resolve({
|
|
25
25
|
[$internal]: true,
|
|
26
26
|
[$resolve](ctx) {
|
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -20,7 +20,8 @@ function normalizeExternalsV2(externals) {
|
|
|
20
20
|
}
|
|
21
21
|
function normalizeMetadata(meta) {
|
|
22
22
|
if (meta.v === 1) {
|
|
23
|
-
const
|
|
23
|
+
const rawExternals = meta.externals;
|
|
24
|
+
const externals = typeof rawExternals === "function" ? rawExternals : () => rawExternals;
|
|
24
25
|
return {
|
|
25
26
|
...meta,
|
|
26
27
|
externals
|
|
@@ -30,7 +31,7 @@ function normalizeMetadata(meta) {
|
|
|
30
31
|
const externals = normalizeExternalsV2(meta?.externals);
|
|
31
32
|
return {
|
|
32
33
|
...meta,
|
|
33
|
-
externals
|
|
34
|
+
externals: () => externals
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
throw new Error(`Unrecognized TypeGPU metadata format: ${safeStringify(meta)}`);
|