@carbonenginejs/runtime-resource 0.18.0 → 0.18.1
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/dist/format/carbonEffect/CjsCarbonEffectWriter.js +16 -4
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -1
- package/dist/format/carbonEffect/buildCarbonEffectContainer.js +11 -1
- package/dist/format/carbonEffect/buildCarbonEffectContainer.js.map +1 -1
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js +36 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -1
- package/dist/format/carbonEffect/carbonEffectRecords.js +45 -1
- package/dist/format/carbonEffect/carbonEffectRecords.js.map +1 -1
- package/dist/format/carbonEffect/carbonEffectResourceTransform.js +120 -60
- package/dist/format/carbonEffect/carbonEffectResourceTransform.js.map +1 -1
- package/dist/format/index.js +1 -1
- package/dist/formats/dds/core/helpers.js +35 -6
- package/dist/formats/dds/core/helpers.js.map +1 -1
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js +53 -1
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -1
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +10 -1
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -1
- package/dist/formats/index.js +3 -0
- package/dist/formats/index.js.map +1 -1
- package/dist/formats/schemabound/CjsSchemaBoundFormat.js +236 -0
- package/dist/formats/schemabound/CjsSchemaBoundFormat.js.map +1 -0
- package/dist/formats/schemabound/core/schemaBoundErrors.js +9 -0
- package/dist/formats/schemabound/core/schemaBoundErrors.js.map +1 -0
- package/dist/formats/schemabound/core/schemaBoundValues.js +307 -0
- package/dist/formats/schemabound/core/schemaBoundValues.js.map +1 -0
- package/dist/formats/schemabound/index.js +2 -0
- package/dist/formats/schemabound/index.js.map +1 -0
- package/dist/formats/sqlite/CjsSqliteFormat.js +244 -0
- package/dist/formats/sqlite/CjsSqliteFormat.js.map +1 -0
- package/dist/formats/sqlite/core/sqlitePages.js +159 -0
- package/dist/formats/sqlite/core/sqlitePages.js.map +1 -0
- package/dist/formats/sqlite/core/sqliteRecords.js +174 -0
- package/dist/formats/sqlite/core/sqliteRecords.js.map +1 -0
- package/dist/formats/sqlite/core/sqliteSchema.js +100 -0
- package/dist/formats/sqlite/core/sqliteSchema.js.map +1 -0
- package/dist/formats/sqlite/index.js +2 -0
- package/dist/formats/sqlite/index.js.map +1 -0
- package/dist/formats/static/CjsStaticFormat.js +220 -0
- package/dist/formats/static/CjsStaticFormat.js.map +1 -0
- package/dist/formats/static/index.js +2 -0
- package/dist/formats/static/index.js.map +1 -0
- package/dist/formats/webgl/core/buildGlslEffectContainer.js +3 -1
- package/dist/formats/webgl/core/buildGlslEffectContainer.js.map +1 -1
- package/dist/formats/webgl/core/effectPackage.js +11 -2
- package/dist/formats/webgl/core/effectPackage.js.map +1 -1
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +10 -2
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -1
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js +3 -1
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js.map +1 -1
- package/dist/formats/webgpu/core/carbonWebgpu/containerViews.js +179 -131
- package/dist/formats/webgpu/core/carbonWebgpu/containerViews.js.map +1 -1
- package/dist/formats/webgpu/core/effectBackendBodySet.js +20 -20
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -1
- package/dist/formats/webgpu/core/packageEffect.js +14 -1
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +9 -1
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +14 -0
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/docs/concepts/shader-resource-model.md +34 -1
- package/docs/formats/README.md +21 -0
- package/docs/formats/carbon-effect-container.md +54 -27
- package/docs/formats/schemabound.md +112 -0
- package/docs/formats/static.md +119 -0
- package/docs/formats/webgl/README.md +5 -3
- package/docs/formats/webgpu/README.md +2 -2
- package/docs/formats/webgpu/architecture.md +2 -2
- package/docs/formats/webgpu/formats/carbon-webgpu.md +13 -2
- package/docs/formats/webgpu/guides/effect-packaging.md +1 -2
- package/docs/formats/webgpu/reference/wgsl-compatibility.md +2 -2
- package/docs/reference/classes/formats.md +33 -0
- package/package.json +4 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column names, taken from the `CREATE TABLE` text SQLite stores verbatim.
|
|
3
|
+
*
|
|
4
|
+
* There is no column catalogue in the file: `sqlite_master` keeps the original
|
|
5
|
+
* statement and nothing else, so the names have to come from parsing it. This
|
|
6
|
+
* reads the column list only — enough to name values — and does not attempt to
|
|
7
|
+
* understand types, constraints or expressions.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Matches the identifier forms SQLite accepts for a column name. */
|
|
11
|
+
const IDENTIFIER = /^(?:"((?:[^"]|"")*)"|`((?:[^`]|``)*)`|\[([^\]]*)\]|([A-Za-z_][A-Za-z0-9_$]*))/u;
|
|
12
|
+
|
|
13
|
+
/** Clauses that begin a table constraint rather than a column definition. */
|
|
14
|
+
const CONSTRAINTS = new Set(["constraint", "primary", "unique", "check", "foreign"]);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Splits the column list at top-level commas.
|
|
18
|
+
*
|
|
19
|
+
* Depth tracking matters because a column can carry a parenthesised type or
|
|
20
|
+
* check, and quoted text can contain either a comma or a bracket.
|
|
21
|
+
*/
|
|
22
|
+
function SplitColumns(body) {
|
|
23
|
+
const parts = [];
|
|
24
|
+
let depth = 0;
|
|
25
|
+
let quote = null;
|
|
26
|
+
let start = 0;
|
|
27
|
+
for (let index = 0; index < body.length; index += 1) {
|
|
28
|
+
const character = body[index];
|
|
29
|
+
if (quote) {
|
|
30
|
+
if (character === quote) {
|
|
31
|
+
quote = null;
|
|
32
|
+
}
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
36
|
+
quote = character;
|
|
37
|
+
} else if (character === "[") {
|
|
38
|
+
quote = "]";
|
|
39
|
+
} else if (character === "(") {
|
|
40
|
+
depth += 1;
|
|
41
|
+
} else if (character === ")") {
|
|
42
|
+
depth -= 1;
|
|
43
|
+
} else if (character === "," && depth === 0) {
|
|
44
|
+
parts.push(body.slice(start, index));
|
|
45
|
+
start = index + 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
parts.push(body.slice(start));
|
|
49
|
+
return parts;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns the column names declared by one `CREATE TABLE` statement.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} sql Statement as stored in `sqlite_master`.
|
|
56
|
+
* @returns {{ names: string[], rowidAlias: number }} Names in declaration
|
|
57
|
+
* order, and the index of an `INTEGER PRIMARY KEY` column if there is one.
|
|
58
|
+
*/
|
|
59
|
+
function ReadColumns(sql) {
|
|
60
|
+
const open = sql.indexOf("(");
|
|
61
|
+
const close = sql.lastIndexOf(")");
|
|
62
|
+
if (open < 0 || close < open) {
|
|
63
|
+
return {
|
|
64
|
+
names: [],
|
|
65
|
+
rowidAlias: -1
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const names = [];
|
|
69
|
+
let rowidAlias = -1;
|
|
70
|
+
for (const part of SplitColumns(sql.slice(open + 1, close))) {
|
|
71
|
+
const text = part.trim();
|
|
72
|
+
if (!text) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const match = IDENTIFIER.exec(text);
|
|
76
|
+
if (!match) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const name = (match[1] ?? match[2] ?? match[3] ?? match[4]).replace(/""/gu, "\"").replace(/``/gu, "`");
|
|
80
|
+
|
|
81
|
+
// A table-level constraint is not a column, and its first word says so.
|
|
82
|
+
if (!match[1] && !match[2] && !match[3] && CONSTRAINTS.has(name.toLowerCase())) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// An INTEGER PRIMARY KEY column IS the rowid: its record value is stored
|
|
87
|
+
// as NULL and the real value only exists in the cell's rowid field.
|
|
88
|
+
if (/^\s*integer\s+primary\s+key\b/iu.test(text.slice(match[0].length))) {
|
|
89
|
+
rowidAlias = names.length;
|
|
90
|
+
}
|
|
91
|
+
names.push(name);
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
names,
|
|
95
|
+
rowidAlias
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { ReadColumns };
|
|
100
|
+
//# sourceMappingURL=sqliteSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqliteSchema.js","sources":["../../../../../src/formats/sqlite/core/sqliteSchema.js"],"sourcesContent":["/**\n * Column names, taken from the `CREATE TABLE` text SQLite stores verbatim.\n *\n * There is no column catalogue in the file: `sqlite_master` keeps the original\n * statement and nothing else, so the names have to come from parsing it. This\n * reads the column list only — enough to name values — and does not attempt to\n * understand types, constraints or expressions.\n */\n\n/** Matches the identifier forms SQLite accepts for a column name. */\nconst IDENTIFIER = /^(?:\"((?:[^\"]|\"\")*)\"|`((?:[^`]|``)*)`|\\[([^\\]]*)\\]|([A-Za-z_][A-Za-z0-9_$]*))/u;\n\n/** Clauses that begin a table constraint rather than a column definition. */\nconst CONSTRAINTS = new Set([\n \"constraint\", \"primary\", \"unique\", \"check\", \"foreign\"\n]);\n\n/**\n * Splits the column list at top-level commas.\n *\n * Depth tracking matters because a column can carry a parenthesised type or\n * check, and quoted text can contain either a comma or a bracket.\n */\nfunction SplitColumns(body) {\n const parts = [];\n let depth = 0;\n let quote = null;\n let start = 0;\n\n for (let index = 0; index < body.length; index += 1) {\n const character = body[index];\n\n if (quote) {\n if (character === quote) {\n quote = null;\n }\n\n continue;\n }\n\n if (character === \"\\\"\" || character === \"'\" || character === \"`\") {\n quote = character;\n } else if (character === \"[\") {\n quote = \"]\";\n } else if (character === \"(\") {\n depth += 1;\n } else if (character === \")\") {\n depth -= 1;\n } else if (character === \",\" && depth === 0) {\n parts.push(body.slice(start, index));\n start = index + 1;\n }\n }\n\n parts.push(body.slice(start));\n\n return parts;\n}\n\n/**\n * Returns the column names declared by one `CREATE TABLE` statement.\n *\n * @param {string} sql Statement as stored in `sqlite_master`.\n * @returns {{ names: string[], rowidAlias: number }} Names in declaration\n * order, and the index of an `INTEGER PRIMARY KEY` column if there is one.\n */\nexport function ReadColumns(sql) {\n const open = sql.indexOf(\"(\");\n const close = sql.lastIndexOf(\")\");\n\n if (open < 0 || close < open) {\n return { names: [], rowidAlias: -1 };\n }\n\n const names = [];\n let rowidAlias = -1;\n\n for (const part of SplitColumns(sql.slice(open + 1, close))) {\n const text = part.trim();\n\n if (!text) {\n continue;\n }\n\n const match = IDENTIFIER.exec(text);\n\n if (!match) {\n continue;\n }\n\n const name = (match[1] ?? match[2] ?? match[3] ?? match[4])\n .replace(/\"\"/gu, \"\\\"\").replace(/``/gu, \"`\");\n\n // A table-level constraint is not a column, and its first word says so.\n if (!match[1] && !match[2] && !match[3] && CONSTRAINTS.has(name.toLowerCase())) {\n continue;\n }\n\n // An INTEGER PRIMARY KEY column IS the rowid: its record value is stored\n // as NULL and the real value only exists in the cell's rowid field.\n if (/^\\s*integer\\s+primary\\s+key\\b/iu.test(text.slice(match[0].length))) {\n rowidAlias = names.length;\n }\n\n names.push(name);\n }\n\n return { names, rowidAlias };\n}\n\nexport default ReadColumns;\n"],"names":["IDENTIFIER","CONSTRAINTS","Set","SplitColumns","body","parts","depth","quote","start","index","length","character","push","slice","ReadColumns","sql","open","indexOf","close","lastIndexOf","names","rowidAlias","part","text","trim","match","exec","name","replace","has","toLowerCase","test"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const SQLITE_SIGNATURE = "SQLite format 3\0";
|
|
2
|
+
const PICKLE_PREFIX_BYTES = 4;
|
|
3
|
+
|
|
4
|
+
/** Container families found behind the single `.static` extension. */
|
|
5
|
+
const CJS_STATIC_FAMILIES = Object.freeze({
|
|
6
|
+
SQLITE: "sqlite",
|
|
7
|
+
PICKLE: "pickle",
|
|
8
|
+
UNKNOWN: "unknown"
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Identifies which container a client `.static` file actually holds.
|
|
13
|
+
*
|
|
14
|
+
* The extension names a role, not a format. Three unrelated containers ship
|
|
15
|
+
* under it, and each fails in its own way when guessed at:
|
|
16
|
+
*
|
|
17
|
+
* - **SQLite 3** — a `cache(key, value, time)` plus `indexes(key, value)`
|
|
18
|
+
* database whose values are JSON documents. `CjsSqliteFormat` reads it.
|
|
19
|
+
* - **Prefixed pickle** — a four-byte little-endian prefix followed by a
|
|
20
|
+
* protocol-0 pickle. Many of these carry class-construction opcodes, which
|
|
21
|
+
* the data-only pickle reader refuses by design; that refusal is correct and
|
|
22
|
+
* is surfaced rather than worked around.
|
|
23
|
+
* - **Schema-bound** — a binary record container whose `.schema` companion is
|
|
24
|
+
* YAML describing its own layout: attribute sizes and types, optional flags,
|
|
25
|
+
* lists with a fixed item size, vectors with a precision, and a key footer of
|
|
26
|
+
* key-to-offset pairs. Nothing needs deriving, because the build ships the
|
|
27
|
+
* layout. Six datasets are stored this way, the celestial tables among them.
|
|
28
|
+
* `CjsSchemaBoundFormat` reads it, given that companion.
|
|
29
|
+
*
|
|
30
|
+
* Detection is signature-based and never executes or trusts file names.
|
|
31
|
+
*
|
|
32
|
+
* **This class identifies and does not decode.** It reports the family, the
|
|
33
|
+
* payload offset and what is still missing; the caller takes that answer to the
|
|
34
|
+
* format that owns the family. It carried a `read()` that dispatched to
|
|
35
|
+
* `CjsPickleFormat` and `CjsSqliteFormat` until 2026-08-15, which made an
|
|
36
|
+
* identification format the routing table for two others and put the decision
|
|
37
|
+
* about what to decode in the wrong place. Nothing outside its own tests ever
|
|
38
|
+
* called it.
|
|
39
|
+
*/
|
|
40
|
+
class CjsStaticFormat {
|
|
41
|
+
/**
|
|
42
|
+
* Report which family a container holds, on the declaration seam.
|
|
43
|
+
*
|
|
44
|
+
* `.static` declares nothing: the extension names a role and every family
|
|
45
|
+
* wears it. The signature is therefore the only claim there is, which is why
|
|
46
|
+
* this format reads it here rather than trusting a name.
|
|
47
|
+
*
|
|
48
|
+
* @param {ArrayBuffer|ArrayBufferView} input Container bytes.
|
|
49
|
+
* @param {object} [options] Probe options.
|
|
50
|
+
* @returns {CjsResourceProbe} Declaration-derived probe.
|
|
51
|
+
*/
|
|
52
|
+
static isSupported(input, options = null) {
|
|
53
|
+
return Probe(this.describe(input), false, options);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Alias for canonical naming.
|
|
58
|
+
*
|
|
59
|
+
* @param {ArrayBuffer|ArrayBufferView} input Container bytes.
|
|
60
|
+
* @param {object} [options] Probe options.
|
|
61
|
+
* @returns {CjsResourceProbe} Declaration-derived probe.
|
|
62
|
+
*/
|
|
63
|
+
static inspect(input, options = null) {
|
|
64
|
+
return this.isSupported(input, options);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Content-verified family resolution.
|
|
69
|
+
*
|
|
70
|
+
* Contract: docs/concepts/format-type-resolution.md. There is no declared
|
|
71
|
+
* type to disagree with here — the extension is silent — so the signature is
|
|
72
|
+
* both the claim and the evidence, and the resolution is always verified.
|
|
73
|
+
* `preferred` names the decode route, and all three now lead into this
|
|
74
|
+
* package: `CjsPickleFormat`, `CjsSqliteFormat`, and `CjsSchemaBoundFormat`
|
|
75
|
+
* once the caller has the `.schema` companion to hand it.
|
|
76
|
+
*
|
|
77
|
+
* @param {ArrayBuffer|ArrayBufferView} input Container bytes.
|
|
78
|
+
* @param {object} [options] Probe options.
|
|
79
|
+
* @returns {Promise<CjsResourceProbe>} Verified probe.
|
|
80
|
+
*/
|
|
81
|
+
static async resolveType(input, options = null) {
|
|
82
|
+
return Probe(this.describe(input), true, options);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Describe one container without decoding it or building a probe.
|
|
87
|
+
*
|
|
88
|
+
* @param {ArrayBuffer|ArrayBufferView} input Container bytes.
|
|
89
|
+
* @returns {object} Family, payload offset, and whether this package decodes it.
|
|
90
|
+
*/
|
|
91
|
+
static describe(input) {
|
|
92
|
+
const bytes = Normalize(input);
|
|
93
|
+
if (MatchesSqlite(bytes)) {
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
family: CJS_STATIC_FAMILIES.SQLITE,
|
|
96
|
+
byteLength: bytes.byteLength,
|
|
97
|
+
payloadOffset: 0,
|
|
98
|
+
prefix: null,
|
|
99
|
+
// Decodable outright since CjsSqliteFormat landed. This reported
|
|
100
|
+
// `requires: "sqlite"` while a caller had to supply an engine, and was
|
|
101
|
+
// the example behind the argument that a capability can depend on the
|
|
102
|
+
// caller's environment - an argument that now needs a different one.
|
|
103
|
+
decodable: true,
|
|
104
|
+
requires: null,
|
|
105
|
+
reason: "Recognized a SQLite container."
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (MatchesPickle(bytes)) {
|
|
109
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
110
|
+
return Object.freeze({
|
|
111
|
+
family: CJS_STATIC_FAMILIES.PICKLE,
|
|
112
|
+
byteLength: bytes.byteLength,
|
|
113
|
+
payloadOffset: PICKLE_PREFIX_BYTES,
|
|
114
|
+
prefix: view.getUint32(0, true),
|
|
115
|
+
decodable: true,
|
|
116
|
+
requires: null,
|
|
117
|
+
reason: null
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
family: CJS_STATIC_FAMILIES.UNKNOWN,
|
|
122
|
+
byteLength: bytes.byteLength,
|
|
123
|
+
payloadOffset: 0,
|
|
124
|
+
prefix: null,
|
|
125
|
+
decodable: false,
|
|
126
|
+
requires: "schema",
|
|
127
|
+
// `decodable` is this format's own answer, and it stays false: these bytes
|
|
128
|
+
// carry nothing to identify, so the family is an inference from the absence
|
|
129
|
+
// of the other two signatures rather than a reading. `requires` names what
|
|
130
|
+
// closes that gap - with the companion, CjsSchemaBoundFormat decodes it.
|
|
131
|
+
reason: "No signature. A schema-bound container needs its .schema companion, " + "which is YAML describing the layout. CjsSchemaBoundFormat reads it from there."
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Return the decodable payload for a container, without its wrapper.
|
|
137
|
+
*
|
|
138
|
+
* @param {ArrayBuffer|ArrayBufferView} input Container bytes.
|
|
139
|
+
* @returns {Uint8Array} Payload bytes.
|
|
140
|
+
*/
|
|
141
|
+
static payload(input) {
|
|
142
|
+
const bytes = Normalize(input);
|
|
143
|
+
const detected = this.describe(bytes);
|
|
144
|
+
return bytes.subarray(detected.payloadOffset);
|
|
145
|
+
}
|
|
146
|
+
static id = "static";
|
|
147
|
+
static extensions = Object.freeze([".static"]);
|
|
148
|
+
static type = Object.freeze(["data"]);
|
|
149
|
+
static mediaTypes = Object.freeze(["data"]);
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The extension is the only input this format claims.
|
|
153
|
+
*
|
|
154
|
+
* Naming the three families here would be a lie in the other direction: a
|
|
155
|
+
* caller cannot hand this format "a pickle" or "a sqlite" and expect it to
|
|
156
|
+
* route, because the whole point of the class is that `.static` declares
|
|
157
|
+
* nothing and the signature has to be read. The family belongs in
|
|
158
|
+
* `describe()`, which measures it, not in a static that asserts it.
|
|
159
|
+
*/
|
|
160
|
+
static inputTypes = Object.freeze(["static"]);
|
|
161
|
+
static outputTypes = Object.freeze(["json", "payload"]);
|
|
162
|
+
static debugOutputTypes = Object.freeze(["raw"]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Build the shared probe payload.
|
|
167
|
+
*
|
|
168
|
+
* Formats report a plain probe-shaped object rather than constructing a
|
|
169
|
+
* `CjsResourceProbe`, which keeps this module free of the decorated class and
|
|
170
|
+
* of the build transform it needs.
|
|
171
|
+
*/
|
|
172
|
+
function Probe(detected, verified, options) {
|
|
173
|
+
return {
|
|
174
|
+
format: "static",
|
|
175
|
+
source: "buffer",
|
|
176
|
+
supported: detected.decodable ? "full" : "partial",
|
|
177
|
+
confidence: detected.family === CJS_STATIC_FAMILIES.UNKNOWN ? 0.5 : 1,
|
|
178
|
+
preferred: detected.family,
|
|
179
|
+
verified,
|
|
180
|
+
reason: detected.reason ?? `Recognized a ${detected.family} container.`,
|
|
181
|
+
variants: [{
|
|
182
|
+
kind: "container",
|
|
183
|
+
codec: detected.family,
|
|
184
|
+
supported: detected.decodable
|
|
185
|
+
}],
|
|
186
|
+
metadata: verified ? {
|
|
187
|
+
...detected,
|
|
188
|
+
declared: null,
|
|
189
|
+
resolved: detected.family,
|
|
190
|
+
mismatch: false
|
|
191
|
+
} : detected,
|
|
192
|
+
...(options || {})
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function MatchesSqlite(bytes) {
|
|
196
|
+
if (bytes.byteLength < SQLITE_SIGNATURE.length) return false;
|
|
197
|
+
for (let index = 0; index < SQLITE_SIGNATURE.length; index++) {
|
|
198
|
+
if (bytes[index] !== SQLITE_SIGNATURE.charCodeAt(index)) return false;
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
function MatchesPickle(bytes) {
|
|
203
|
+
// A protocol-0 pickle opens a container then names it: "(dp1\n" or "(lp1\n".
|
|
204
|
+
if (bytes.byteLength < PICKLE_PREFIX_BYTES + 3) return false;
|
|
205
|
+
if (bytes[PICKLE_PREFIX_BYTES] !== 0x28) return false;
|
|
206
|
+
const kind = bytes[PICKLE_PREFIX_BYTES + 1];
|
|
207
|
+
return kind === 0x64 || kind === 0x6c;
|
|
208
|
+
}
|
|
209
|
+
function Normalize(input) {
|
|
210
|
+
if (input instanceof ArrayBuffer) return new Uint8Array(input);
|
|
211
|
+
if (ArrayBuffer.isView(input)) {
|
|
212
|
+
return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
213
|
+
}
|
|
214
|
+
const error = new TypeError("A .static container must be an ArrayBuffer or a view over one.");
|
|
215
|
+
error.code = "CJS_STATIC_INPUT_INVALID";
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { CJS_STATIC_FAMILIES, CjsStaticFormat };
|
|
220
|
+
//# sourceMappingURL=CjsStaticFormat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CjsStaticFormat.js","sources":["../../../../src/formats/static/CjsStaticFormat.js"],"sourcesContent":["\nconst SQLITE_SIGNATURE = \"SQLite format 3\\0\";\nconst PICKLE_PREFIX_BYTES = 4;\n\n/** Container families found behind the single `.static` extension. */\nexport const CJS_STATIC_FAMILIES = Object.freeze({\n SQLITE: \"sqlite\",\n PICKLE: \"pickle\",\n UNKNOWN: \"unknown\"\n});\n\n/**\n * Identifies which container a client `.static` file actually holds.\n *\n * The extension names a role, not a format. Three unrelated containers ship\n * under it, and each fails in its own way when guessed at:\n *\n * - **SQLite 3** — a `cache(key, value, time)` plus `indexes(key, value)`\n * database whose values are JSON documents. `CjsSqliteFormat` reads it.\n * - **Prefixed pickle** — a four-byte little-endian prefix followed by a\n * protocol-0 pickle. Many of these carry class-construction opcodes, which\n * the data-only pickle reader refuses by design; that refusal is correct and\n * is surfaced rather than worked around.\n * - **Schema-bound** — a binary record container whose `.schema` companion is\n * YAML describing its own layout: attribute sizes and types, optional flags,\n * lists with a fixed item size, vectors with a precision, and a key footer of\n * key-to-offset pairs. Nothing needs deriving, because the build ships the\n * layout. Six datasets are stored this way, the celestial tables among them.\n * `CjsSchemaBoundFormat` reads it, given that companion.\n *\n * Detection is signature-based and never executes or trusts file names.\n *\n * **This class identifies and does not decode.** It reports the family, the\n * payload offset and what is still missing; the caller takes that answer to the\n * format that owns the family. It carried a `read()` that dispatched to\n * `CjsPickleFormat` and `CjsSqliteFormat` until 2026-08-15, which made an\n * identification format the routing table for two others and put the decision\n * about what to decode in the wrong place. Nothing outside its own tests ever\n * called it.\n */\nexport class CjsStaticFormat\n{\n\n /**\n * Report which family a container holds, on the declaration seam.\n *\n * `.static` declares nothing: the extension names a role and every family\n * wears it. The signature is therefore the only claim there is, which is why\n * this format reads it here rather than trusting a name.\n *\n * @param {ArrayBuffer|ArrayBufferView} input Container bytes.\n * @param {object} [options] Probe options.\n * @returns {CjsResourceProbe} Declaration-derived probe.\n */\n static isSupported(input, options = null)\n {\n return Probe(this.describe(input), false, options);\n }\n\n /**\n * Alias for canonical naming.\n *\n * @param {ArrayBuffer|ArrayBufferView} input Container bytes.\n * @param {object} [options] Probe options.\n * @returns {CjsResourceProbe} Declaration-derived probe.\n */\n static inspect(input, options = null)\n {\n return this.isSupported(input, options);\n }\n\n /**\n * Content-verified family resolution.\n *\n * Contract: docs/concepts/format-type-resolution.md. There is no declared\n * type to disagree with here — the extension is silent — so the signature is\n * both the claim and the evidence, and the resolution is always verified.\n * `preferred` names the decode route, and all three now lead into this\n * package: `CjsPickleFormat`, `CjsSqliteFormat`, and `CjsSchemaBoundFormat`\n * once the caller has the `.schema` companion to hand it.\n *\n * @param {ArrayBuffer|ArrayBufferView} input Container bytes.\n * @param {object} [options] Probe options.\n * @returns {Promise<CjsResourceProbe>} Verified probe.\n */\n static async resolveType(input, options = null)\n {\n return Probe(this.describe(input), true, options);\n }\n\n /**\n * Describe one container without decoding it or building a probe.\n *\n * @param {ArrayBuffer|ArrayBufferView} input Container bytes.\n * @returns {object} Family, payload offset, and whether this package decodes it.\n */\n static describe(input)\n {\n const bytes = Normalize(input);\n\n if (MatchesSqlite(bytes))\n {\n return Object.freeze({\n family: CJS_STATIC_FAMILIES.SQLITE,\n byteLength: bytes.byteLength,\n payloadOffset: 0,\n prefix: null,\n // Decodable outright since CjsSqliteFormat landed. This reported\n // `requires: \"sqlite\"` while a caller had to supply an engine, and was\n // the example behind the argument that a capability can depend on the\n // caller's environment - an argument that now needs a different one.\n decodable: true,\n requires: null,\n reason: \"Recognized a SQLite container.\"\n });\n }\n\n if (MatchesPickle(bytes))\n {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n return Object.freeze({\n family: CJS_STATIC_FAMILIES.PICKLE,\n byteLength: bytes.byteLength,\n payloadOffset: PICKLE_PREFIX_BYTES,\n prefix: view.getUint32(0, true),\n decodable: true,\n requires: null,\n reason: null\n });\n }\n\n return Object.freeze({\n family: CJS_STATIC_FAMILIES.UNKNOWN,\n byteLength: bytes.byteLength,\n payloadOffset: 0,\n prefix: null,\n decodable: false,\n requires: \"schema\",\n // `decodable` is this format's own answer, and it stays false: these bytes\n // carry nothing to identify, so the family is an inference from the absence\n // of the other two signatures rather than a reading. `requires` names what\n // closes that gap - with the companion, CjsSchemaBoundFormat decodes it.\n reason: \"No signature. A schema-bound container needs its .schema companion, \"\n + \"which is YAML describing the layout. CjsSchemaBoundFormat reads it from there.\"\n });\n }\n\n /**\n * Return the decodable payload for a container, without its wrapper.\n *\n * @param {ArrayBuffer|ArrayBufferView} input Container bytes.\n * @returns {Uint8Array} Payload bytes.\n */\n static payload(input)\n {\n const bytes = Normalize(input);\n const detected = this.describe(bytes);\n\n return bytes.subarray(detected.payloadOffset);\n }\n\n\n static id = \"static\";\n static extensions = Object.freeze([ \".static\" ]);\n static type = Object.freeze([ \"data\" ]);\n static mediaTypes = Object.freeze([ \"data\" ]);\n\n /**\n * The extension is the only input this format claims.\n *\n * Naming the three families here would be a lie in the other direction: a\n * caller cannot hand this format \"a pickle\" or \"a sqlite\" and expect it to\n * route, because the whole point of the class is that `.static` declares\n * nothing and the signature has to be read. The family belongs in\n * `describe()`, which measures it, not in a static that asserts it.\n */\n static inputTypes = Object.freeze([ \"static\" ]);\n static outputTypes = Object.freeze([ \"json\", \"payload\" ]);\n static debugOutputTypes = Object.freeze([ \"raw\" ]);\n\n}\n\n/**\n * Build the shared probe payload.\n *\n * Formats report a plain probe-shaped object rather than constructing a\n * `CjsResourceProbe`, which keeps this module free of the decorated class and\n * of the build transform it needs.\n */\nfunction Probe(detected, verified, options)\n{\n return {\n format: \"static\",\n source: \"buffer\",\n supported: detected.decodable ? \"full\" : \"partial\",\n confidence: detected.family === CJS_STATIC_FAMILIES.UNKNOWN ? 0.5 : 1,\n preferred: detected.family,\n verified,\n reason: detected.reason ?? `Recognized a ${detected.family} container.`,\n variants: [ { kind: \"container\", codec: detected.family, supported: detected.decodable } ],\n metadata: verified\n ? { ...detected, declared: null, resolved: detected.family, mismatch: false }\n : detected,\n ...(options || {})\n };\n}\n\nfunction MatchesSqlite(bytes)\n{\n if (bytes.byteLength < SQLITE_SIGNATURE.length) return false;\n\n for (let index = 0; index < SQLITE_SIGNATURE.length; index++)\n {\n if (bytes[index] !== SQLITE_SIGNATURE.charCodeAt(index)) return false;\n }\n\n return true;\n}\n\nfunction MatchesPickle(bytes)\n{\n // A protocol-0 pickle opens a container then names it: \"(dp1\\n\" or \"(lp1\\n\".\n if (bytes.byteLength < PICKLE_PREFIX_BYTES + 3) return false;\n if (bytes[PICKLE_PREFIX_BYTES] !== 0x28) return false;\n\n const kind = bytes[PICKLE_PREFIX_BYTES + 1];\n\n return kind === 0x64 || kind === 0x6c;\n}\n\nfunction Normalize(input)\n{\n if (input instanceof ArrayBuffer) return new Uint8Array(input);\n\n if (ArrayBuffer.isView(input))\n {\n return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);\n }\n\n const error = new TypeError(\"A .static container must be an ArrayBuffer or a view over one.\");\n\n error.code = \"CJS_STATIC_INPUT_INVALID\";\n throw error;\n}\n"],"names":["SQLITE_SIGNATURE","PICKLE_PREFIX_BYTES","CJS_STATIC_FAMILIES","Object","freeze","SQLITE","PICKLE","UNKNOWN","CjsStaticFormat","isSupported","input","options","Probe","describe","inspect","resolveType","bytes","Normalize","MatchesSqlite","family","byteLength","payloadOffset","prefix","decodable","requires","reason","MatchesPickle","view","DataView","buffer","byteOffset","getUint32","payload","detected","subarray","id","extensions","type","mediaTypes","inputTypes","outputTypes","debugOutputTypes","verified","format","source","supported","confidence","preferred","variants","kind","codec","metadata","declared","resolved","mismatch","length","index","charCodeAt","ArrayBuffer","Uint8Array","isView","error","TypeError","code"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -55,9 +55,11 @@ const GLSL_CONTAINER_BACKEND = Object.freeze({
|
|
|
55
55
|
* Builds the complete WebGL 2 effect container.
|
|
56
56
|
*
|
|
57
57
|
* @param {object} effectRes Loaded version-15 `Tr2EffectRes`.
|
|
58
|
-
* @param {object} permutationGraph Validated `
|
|
58
|
+
* @param {object} permutationGraph Validated derived `CJS_EFFECT_PERMUTATION_GRAPH` document (no chunk is stored).
|
|
59
59
|
* @param {object} backendBodySet Translated GLSL bodies.
|
|
60
60
|
* @param {object} [options] Container options.
|
|
61
|
+
* @param {number} [options.version] Container data version to emit; defaults to
|
|
62
|
+
* the current version. Independent of the source effect's version.
|
|
61
63
|
* @param {number[]|Uint8Array} [options.compilerVersion] Four version bytes.
|
|
62
64
|
* @param {string} [options.sourceHash] 32 ASCII hash characters.
|
|
63
65
|
* @returns {{bytes:Uint8Array, permutationCount:number, bodyCount:number}} Container and its body accounting.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildGlslEffectContainer.js","sources":["../../../../../src/formats/webgl/core/buildGlslEffectContainer.js"],"sourcesContent":["import {\n buildCarbonEffectContainer\n} from \"../../../format/carbonEffect/buildCarbonEffectContainer.js\";\nimport { writeGlslBackendBlock } from \"./glslBackendBlock.js\";\n\n/**\n * The WebGL 2 backend adapter for the shared Carbon container builder.\n *\n * The record layout, the permutation walk and the description mapping are shared\n * with WebGPU and live in `format/carbonEffect/buildCarbonEffectContainer.js`.\n * What remains here is the two backend-varying decisions: a program is GLSL ES\n * 3.00 text, and a pass's trailing block is the GLSL lowering data.\n *\n * There is no entry-point assertion to make. GLSL's entry point is `main` by\n * language rule rather than by our emitter's choice, so unlike WGSL there is\n * nothing a future lowerer could change.\n */\n\n/**\n * Encodes one GLSL stage program.\n *\n * @param {object} shader Translated shader record.\n * @returns {Uint8Array} Program bytes.\n */\nfunction encodeProgram(shader)\n{\n return new TextEncoder().encode(shader.code);\n}\n\n/**\n * Builds the per-pass backend block for one pass of one translated body.\n *\n * A pass whose stages added no lowering data emits no block at all rather than\n * an empty one, so the description ends where Carbon's would and the optional\n * block stays genuinely optional.\n *\n * @param {object} unit Pass translation unit.\n * @param {string} passKey Enclosing pass key.\n * @returns {Uint8Array|null} Block bytes, or null when the pass has none.\n */\nfunction encodeBackendBlock(unit, passKey)\n{\n const stages = unit.block;\n const transforms = (unit.resourceTransforms ?? [])\n .filter((transform) => transform.layoutKey === passKey);\n\n if (!stages && !transforms.length) return null;\n\n return writeGlslBackendBlock({ stages: stages ?? {}, transforms });\n}\n\n/** The WebGL encoders, as the shared builder's backend argument. */\nexport const GLSL_CONTAINER_BACKEND = Object.freeze({ encodeProgram, encodeBackendBlock });\n\n/**\n * Builds the complete WebGL 2 effect container.\n *\n * @param {object} effectRes Loaded version-15 `Tr2EffectRes`.\n * @param {object} permutationGraph Validated `
|
|
1
|
+
{"version":3,"file":"buildGlslEffectContainer.js","sources":["../../../../../src/formats/webgl/core/buildGlslEffectContainer.js"],"sourcesContent":["import {\n buildCarbonEffectContainer\n} from \"../../../format/carbonEffect/buildCarbonEffectContainer.js\";\nimport { writeGlslBackendBlock } from \"./glslBackendBlock.js\";\n\n/**\n * The WebGL 2 backend adapter for the shared Carbon container builder.\n *\n * The record layout, the permutation walk and the description mapping are shared\n * with WebGPU and live in `format/carbonEffect/buildCarbonEffectContainer.js`.\n * What remains here is the two backend-varying decisions: a program is GLSL ES\n * 3.00 text, and a pass's trailing block is the GLSL lowering data.\n *\n * There is no entry-point assertion to make. GLSL's entry point is `main` by\n * language rule rather than by our emitter's choice, so unlike WGSL there is\n * nothing a future lowerer could change.\n */\n\n/**\n * Encodes one GLSL stage program.\n *\n * @param {object} shader Translated shader record.\n * @returns {Uint8Array} Program bytes.\n */\nfunction encodeProgram(shader)\n{\n return new TextEncoder().encode(shader.code);\n}\n\n/**\n * Builds the per-pass backend block for one pass of one translated body.\n *\n * A pass whose stages added no lowering data emits no block at all rather than\n * an empty one, so the description ends where Carbon's would and the optional\n * block stays genuinely optional.\n *\n * @param {object} unit Pass translation unit.\n * @param {string} passKey Enclosing pass key.\n * @returns {Uint8Array|null} Block bytes, or null when the pass has none.\n */\nfunction encodeBackendBlock(unit, passKey)\n{\n const stages = unit.block;\n const transforms = (unit.resourceTransforms ?? [])\n .filter((transform) => transform.layoutKey === passKey);\n\n if (!stages && !transforms.length) return null;\n\n return writeGlslBackendBlock({ stages: stages ?? {}, transforms });\n}\n\n/** The WebGL encoders, as the shared builder's backend argument. */\nexport const GLSL_CONTAINER_BACKEND = Object.freeze({ encodeProgram, encodeBackendBlock });\n\n/**\n * Builds the complete WebGL 2 effect container.\n *\n * @param {object} effectRes Loaded version-15 `Tr2EffectRes`.\n * @param {object} permutationGraph Validated derived `CJS_EFFECT_PERMUTATION_GRAPH` document (no chunk is stored).\n * @param {object} backendBodySet Translated GLSL bodies.\n * @param {object} [options] Container options.\n * @param {number} [options.version] Container data version to emit; defaults to\n * the current version. Independent of the source effect's version.\n * @param {number[]|Uint8Array} [options.compilerVersion] Four version bytes.\n * @param {string} [options.sourceHash] 32 ASCII hash characters.\n * @returns {{bytes:Uint8Array, permutationCount:number, bodyCount:number}} Container and its body accounting.\n */\nexport function buildGlslEffectContainer(\n effectRes,\n permutationGraph,\n backendBodySet,\n options = {}\n)\n{\n return buildCarbonEffectContainer(\n effectRes,\n permutationGraph,\n backendBodySet,\n GLSL_CONTAINER_BACKEND,\n options\n );\n}\n\nexport default buildGlslEffectContainer;\n"],"names":["encodeProgram","shader","TextEncoder","encode","code","encodeBackendBlock","unit","passKey","stages","block","transforms","resourceTransforms","filter","transform","layoutKey","length","writeGlslBackendBlock","GLSL_CONTAINER_BACKEND","Object","freeze","buildGlslEffectContainer","effectRes","permutationGraph","backendBodySet","options","buildCarbonEffectContainer"],"mappings":";;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,aAAaA,CAACC,MAAM,EAC7B;EACI,OAAO,IAAIC,WAAW,EAAE,CAACC,MAAM,CAACF,MAAM,CAACG,IAAI,CAAC;AAChD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,kBAAkBA,CAACC,IAAI,EAAEC,OAAO,EACzC;AACI,EAAA,MAAMC,MAAM,GAAGF,IAAI,CAACG,KAAK;AACzB,EAAA,MAAMC,UAAU,GAAG,CAACJ,IAAI,CAACK,kBAAkB,IAAI,EAAE,EAC5CC,MAAM,CAAEC,SAAS,IAAKA,SAAS,CAACC,SAAS,KAAKP,OAAO,CAAC;EAE3D,IAAI,CAACC,MAAM,IAAI,CAACE,UAAU,CAACK,MAAM,EAAE,OAAO,IAAI;AAE9C,EAAA,OAAOC,qBAAqB,CAAC;AAAER,IAAAA,MAAM,EAAEA,MAAM,IAAI,EAAE;AAAEE,IAAAA;AAAW,GAAC,CAAC;AACtE;;AAEA;MACaO,sBAAsB,GAAGC,MAAM,CAACC,MAAM,CAAC;EAAEnB,aAAa;AAAEK,EAAAA;AAAmB,CAAC;;AAEzF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASe,wBAAwBA,CACpCC,SAAS,EACTC,gBAAgB,EAChBC,cAAc,EACdC,OAAO,GAAG,EAAE,EAEhB;EACI,OAAOC,0BAA0B,CAC7BJ,SAAS,EACTC,gBAAgB,EAChBC,cAAc,EACdN,sBAAsB,EACtBO,OACJ,CAAC;AACL;;;;"}
|
|
@@ -3,7 +3,7 @@ import { HlslRenderContextEnum, hlslShaderStageName } from '../../hlsl/core/tr2/
|
|
|
3
3
|
import '@carbonenginejs/runtime-utils/bytes';
|
|
4
4
|
import '../../hlsl/core/carbonDescriptionToRuntime.js';
|
|
5
5
|
import '../../../format/CjsByteReader.js';
|
|
6
|
-
import '../../../format/
|
|
6
|
+
import { resolveWriteVersion } from '../../../format/carbonEffect/carbonEffectRecords.js';
|
|
7
7
|
import { HlslEffectBindingManifest } from '../../hlsl/core/tr2/shader/HlslEffectBindingManifest.js';
|
|
8
8
|
import { buildEffectPermutationGraph, EFFECT_PERMUTATION_GRAPH_VERSION, EFFECT_PERMUTATION_GRAPH_FORMAT } from '../../../format/effect/effectPermutationGraph.js';
|
|
9
9
|
import { emitGlslWithOptions } from './helpers.js';
|
|
@@ -38,6 +38,9 @@ const PACKAGE_VERSION = "0.11.1";
|
|
|
38
38
|
*/
|
|
39
39
|
function buildEffectPackage(input, options = {}) {
|
|
40
40
|
const values = normalizeOptions(input, options);
|
|
41
|
+
// Resolved before any translation work, so an unwritable version is refused
|
|
42
|
+
// up front. What lands in `info.containerVersion` is what was emitted.
|
|
43
|
+
const containerVersion = resolveWriteVersion(options.version);
|
|
41
44
|
const effectRes = CjsHlslFormat.read(values.sourceBytes, {
|
|
42
45
|
emit: CjsHlslFormat.OUTPUT_RAW,
|
|
43
46
|
source: values.source
|
|
@@ -155,6 +158,11 @@ function buildEffectPackage(input, options = {}) {
|
|
|
155
158
|
format: "CARBON_WEBGL",
|
|
156
159
|
formatVersion: EFFECT_INFO_VERSION,
|
|
157
160
|
packageKind: values.allPermutations ? "tr2-effect-webgl-permutations" : "tr2-effect-webgl",
|
|
161
|
+
// What these bytes ARE, next to `sourceEffectVersion` below, which is
|
|
162
|
+
// what they were read FROM. The reader accepts 8..15; the writer emits
|
|
163
|
+
// 15 only, so the two are not the same number and a consumer must not
|
|
164
|
+
// infer one from the other.
|
|
165
|
+
containerVersion,
|
|
158
166
|
targetBackend: "webgl",
|
|
159
167
|
backendPackage: "@carbonenginejs/runtime-resource/formats/webgl",
|
|
160
168
|
backendPackageVersion: PACKAGE_VERSION,
|
|
@@ -270,7 +278,8 @@ function buildEffectPackage(input, options = {}) {
|
|
|
270
278
|
permutationGraph
|
|
271
279
|
});
|
|
272
280
|
const container = buildGlslEffectContainer(effectRes, permutationGraph, backendBodySet, {
|
|
273
|
-
compilerVersion: effectRes.m_compilerVersionBytes
|
|
281
|
+
compilerVersion: effectRes.m_compilerVersionBytes,
|
|
282
|
+
version: containerVersion
|
|
274
283
|
});
|
|
275
284
|
const bytes = container.bytes;
|
|
276
285
|
const inspection = inspectGlslEffectContainer(bytes, {
|