@carbonenginejs/runtime-resource 0.16.0 → 0.17.0
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/CjsFormat.js +84 -83
- package/dist/format/CjsFormat.js.map +1 -1
- package/dist/format/CjsResourceProbe.js +87 -86
- package/dist/format/CjsResourceProbe.js.map +1 -1
- package/dist/format/carbonEffect/backendEngineId.js +100 -0
- package/dist/format/carbonEffect/backendEngineId.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js +23 -23
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -1
- package/dist/format/index.js +1 -1
- package/dist/formats/png/core/helpers.js +27 -8
- package/dist/formats/png/core/helpers.js.map +1 -1
- package/dist/formats/webgl/core/effectPackage.js +141 -53
- package/dist/formats/webgl/core/effectPackage.js.map +1 -1
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +799 -456
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -1
- package/dist/formats/webgl/core/glslBackendBlock.js +70 -27
- package/dist/formats/webgl/core/glslBackendBlock.js.map +1 -1
- package/dist/formats/webgl/core/helpers.js +53 -53
- package/dist/formats/webgl/core/helpers.js.map +1 -1
- package/dist/formats/webgl/core/readGlslEffectContainer.js +82 -67
- package/dist/formats/webgl/core/readGlslEffectContainer.js.map +1 -1
- package/dist/formats/webgpu/core/carbonWebgpu/CarbonWebgpuContainer.js +10 -1
- package/dist/formats/webgpu/core/carbonWebgpu/CarbonWebgpuContainer.js.map +1 -1
- package/dist/formats/wem/CjsWemFormat.js +121 -121
- package/dist/formats/wem/CjsWemFormat.js.map +1 -1
- package/dist/formats/wem/core/resolve.js +8 -8
- package/dist/formats/wem/core/resolve.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +102 -60
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/docs/concepts/format-type-resolution.md +79 -0
- package/docs/formats/README.md +11 -0
- package/docs/formats/wwise.md +25 -0
- package/docs/roadmap.md +19 -0
- package/package.json +1 -1
|
@@ -13,11 +13,11 @@ import { requireShaderStageType } from './shaderStage.js';
|
|
|
13
13
|
// Source: trinity/trinity/Shader/Tr2EffectDescription.h
|
|
14
14
|
// Source: trinity/trinity/Shader/Tr2EffectDescription.cpp
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* The offset word a zero-size blob carries, or the null sentinel.
|
|
18
|
-
*
|
|
19
|
-
* @param {{size:number,offset:number}} ref Blob reference.
|
|
20
|
-
* @returns {number} Offset word worth retaining.
|
|
16
|
+
/**
|
|
17
|
+
* The offset word a zero-size blob carries, or the null sentinel.
|
|
18
|
+
*
|
|
19
|
+
* @param {{size:number,offset:number}} ref Blob reference.
|
|
20
|
+
* @returns {number} Offset word worth retaining.
|
|
21
21
|
*/
|
|
22
22
|
function unsetOffsetOf(ref) {
|
|
23
23
|
return ref.size === 0 ? ref.offset : 0xffffffff;
|
|
@@ -61,12 +61,54 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
61
61
|
/** Exact source program metadata and owned bytes, before backend realization. */
|
|
62
62
|
sourceProgram = null;
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
// Ported from CarbonEngine (MIT, (c) 2026 CCP Games) - https://github.com/carbonengine/trinity
|
|
65
|
+
// trinity/Shader/Tr2Effect.cpp:1799-1821 (the sizing loop and its assertion)
|
|
66
|
+
//
|
|
67
|
+
// Carbon's comment at the site is the whole rule: "Figure out how large the
|
|
68
|
+
// constant buffer has to be. This has to be done even if the constant isn't
|
|
69
|
+
// set, as the shader may still sample it and expect to get some kind of
|
|
70
|
+
// default (usually zero)." So EVERY constant participates, not only the ones
|
|
71
|
+
// an effect binds a parameter to.
|
|
72
|
+
//
|
|
73
|
+
// THIS IS NOT `constantValueSize`, AND THE DIFFERENCE IS EASY TO MISS.
|
|
74
|
+
// `constantValueSize` is the length of the authored DEFAULT blob, which
|
|
75
|
+
// Carbon separately grows to cover autoregister sampler-index constants
|
|
76
|
+
// (Tr2EffectDescription.cpp:629-632). Carbon asserts
|
|
77
|
+
// `constantSize >= constantDefaultValueSize` precisely because the two are
|
|
78
|
+
// different numbers and the defaults are a PREFIX of the buffer. An effect
|
|
79
|
+
// that authors defaults for only some of its constants makes them differ, so
|
|
80
|
+
// using the default size as the buffer size is right until it silently is
|
|
81
|
+
// not.
|
|
82
|
+
//
|
|
83
|
+
// It lives here rather than in a consumer because it is arithmetic over this
|
|
84
|
+
// object's own constants and gives every backend the same answer. A backend
|
|
85
|
+
// then applies its own alignment on top - WebGPU's uniform binding alignment,
|
|
86
|
+
// std140 for a WebGL2 block - and that padding is the backend's, not this.
|
|
87
|
+
// Decision 4 of the engine backends plan names the alternative as a defect
|
|
88
|
+
// worth declining to inherit: Carbon replicates its draw-argument arithmetic
|
|
89
|
+
// across ten call sites, and this would replicate the same way once a second
|
|
90
|
+
// engine exists.
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The byte size a constant buffer must have to hold every declared constant.
|
|
94
|
+
*
|
|
95
|
+
* Always at least `constantValueSize`, because the authored defaults occupy
|
|
96
|
+
* the start of the same buffer.
|
|
97
|
+
*/
|
|
98
|
+
GetConstantBufferSize() {
|
|
99
|
+
let size = 0;
|
|
100
|
+
for (const constant of this.constants) {
|
|
101
|
+
size = Math.max(size, (constant?.offset ?? 0) + (constant?.size ?? 0));
|
|
102
|
+
}
|
|
103
|
+
return Math.max(size, this.constantValueSize);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Construct one canonical stage input from JS/JSON model values.
|
|
108
|
+
*
|
|
109
|
+
* @param {object} values Canonical model values.
|
|
110
|
+
* @param {object} options CjsModel import options.
|
|
111
|
+
* @returns {Tr2EffectStageInput} Hydrated stage input.
|
|
70
112
|
*/
|
|
71
113
|
static from(values = {}, options = {}) {
|
|
72
114
|
let normalized = values;
|
|
@@ -87,11 +129,11 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
87
129
|
return stage;
|
|
88
130
|
}
|
|
89
131
|
|
|
90
|
-
/**
|
|
91
|
-
* Hydrate one canonical stage input from a decoded Carbon binary record.
|
|
92
|
-
*
|
|
93
|
-
* @param {object} record Decoded Carbon stage record.
|
|
94
|
-
* @returns {Tr2EffectStageInput} Hydrated canonical stage input.
|
|
132
|
+
/**
|
|
133
|
+
* Hydrate one canonical stage input from a decoded Carbon binary record.
|
|
134
|
+
*
|
|
135
|
+
* @param {object} record Decoded Carbon stage record.
|
|
136
|
+
* @returns {Tr2EffectStageInput} Hydrated canonical stage input.
|
|
95
137
|
*/
|
|
96
138
|
static fromCarbonBinary(record) {
|
|
97
139
|
if (!isPlainObject(record)) {
|
|
@@ -124,22 +166,22 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
124
166
|
return input;
|
|
125
167
|
}
|
|
126
168
|
|
|
127
|
-
/**
|
|
128
|
-
* Build one stage input from a Carbon v15 `StageData` block.
|
|
129
|
-
*
|
|
130
|
-
* A raytracing library's global and local inputs are the same block without a
|
|
131
|
-
* stage wrapper — no stage type, no pipeline inputs, no thread group, no
|
|
132
|
-
* program of their own — so this is the half both callers share and
|
|
133
|
-
* `fromCarbonBinary` is the stage-only remainder layered on top.
|
|
134
|
-
*
|
|
135
|
-
* Carbon writes textures, samplers and UAVs in ascending register order because
|
|
136
|
-
* they are `std::map`s, and they are re-keyed by register here rather than by
|
|
137
|
-
* position, so the map is authoritative and the record's order is not load
|
|
138
|
-
* bearing.
|
|
139
|
-
*
|
|
140
|
-
* @param {object} record Carbon stage-data record.
|
|
141
|
-
* @param {number} [stageType] Stage index, or -1 for a library input.
|
|
142
|
-
* @returns {Tr2EffectStageInput} Reflected stage input.
|
|
169
|
+
/**
|
|
170
|
+
* Build one stage input from a Carbon v15 `StageData` block.
|
|
171
|
+
*
|
|
172
|
+
* A raytracing library's global and local inputs are the same block without a
|
|
173
|
+
* stage wrapper — no stage type, no pipeline inputs, no thread group, no
|
|
174
|
+
* program of their own — so this is the half both callers share and
|
|
175
|
+
* `fromCarbonBinary` is the stage-only remainder layered on top.
|
|
176
|
+
*
|
|
177
|
+
* Carbon writes textures, samplers and UAVs in ascending register order because
|
|
178
|
+
* they are `std::map`s, and they are re-keyed by register here rather than by
|
|
179
|
+
* position, so the map is authoritative and the record's order is not load
|
|
180
|
+
* bearing.
|
|
181
|
+
*
|
|
182
|
+
* @param {object} record Carbon stage-data record.
|
|
183
|
+
* @param {number} [stageType] Stage index, or -1 for a library input.
|
|
184
|
+
* @returns {Tr2EffectStageInput} Reflected stage input.
|
|
143
185
|
*/
|
|
144
186
|
static fromCarbonBinaryInput(record, stageType = -1) {
|
|
145
187
|
if (!isPlainObject(record)) {
|
|
@@ -205,10 +247,10 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
205
247
|
return input;
|
|
206
248
|
}
|
|
207
249
|
|
|
208
|
-
/**
|
|
209
|
-
* Emit this stage as a Carbon v15 stage record.
|
|
210
|
-
*
|
|
211
|
-
* @returns {object} Carbon stage record.
|
|
250
|
+
/**
|
|
251
|
+
* Emit this stage as a Carbon v15 stage record.
|
|
252
|
+
*
|
|
253
|
+
* @returns {object} Carbon stage record.
|
|
212
254
|
*/
|
|
213
255
|
toCarbonBinary() {
|
|
214
256
|
const signature = this.signature ?? {};
|
|
@@ -229,17 +271,17 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
229
271
|
};
|
|
230
272
|
}
|
|
231
273
|
|
|
232
|
-
/**
|
|
233
|
-
* Emit this input as a Carbon v15 `StageData` block.
|
|
234
|
-
*
|
|
235
|
-
* Carbon holds textures, samplers, UAVs and render states in `std::map`s and
|
|
236
|
-
* writes them in key order, and it sorts annotation names by `strcmp` before
|
|
237
|
-
* writing. Our maps are keyed but not ordered, so every collection is sorted
|
|
238
|
-
* explicitly here rather than trusting insertion order — the reader is
|
|
239
|
-
* indifferent, but the bytes are not, and a container that disagrees with
|
|
240
|
-
* Carbon's ordering is not the file Carbon would have written.
|
|
241
|
-
*
|
|
242
|
-
* @returns {object} Carbon stage-data record.
|
|
274
|
+
/**
|
|
275
|
+
* Emit this input as a Carbon v15 `StageData` block.
|
|
276
|
+
*
|
|
277
|
+
* Carbon holds textures, samplers, UAVs and render states in `std::map`s and
|
|
278
|
+
* writes them in key order, and it sorts annotation names by `strcmp` before
|
|
279
|
+
* writing. Our maps are keyed but not ordered, so every collection is sorted
|
|
280
|
+
* explicitly here rather than trusting insertion order — the reader is
|
|
281
|
+
* indifferent, but the bytes are not, and a container that disagrees with
|
|
282
|
+
* Carbon's ordering is not the file Carbon would have written.
|
|
283
|
+
*
|
|
284
|
+
* @returns {object} Carbon stage-data record.
|
|
243
285
|
*/
|
|
244
286
|
toCarbonBinaryInput() {
|
|
245
287
|
const byRegister = (left, right) => left.registerIndex - right.registerIndex;
|
|
@@ -305,11 +347,11 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
305
347
|
return result;
|
|
306
348
|
}
|
|
307
349
|
|
|
308
|
-
/**
|
|
309
|
-
* Create one explicit absent stage slot.
|
|
310
|
-
*
|
|
311
|
-
* @param {number} stageType Stage index.
|
|
312
|
-
* @returns {Tr2EffectStageInput} Empty stage input.
|
|
350
|
+
/**
|
|
351
|
+
* Create one explicit absent stage slot.
|
|
352
|
+
*
|
|
353
|
+
* @param {number} stageType Stage index.
|
|
354
|
+
* @returns {Tr2EffectStageInput} Empty stage input.
|
|
313
355
|
*/
|
|
314
356
|
static createEmpty(stageType) {
|
|
315
357
|
const stage = new this();
|
|
@@ -317,14 +359,14 @@ class Tr2EffectStageInput extends CjsModel {
|
|
|
317
359
|
return stage;
|
|
318
360
|
}
|
|
319
361
|
|
|
320
|
-
/**
|
|
321
|
-
* Normalize one register-indexed collection into its canonical typed map.
|
|
322
|
-
*
|
|
323
|
-
* @param {Map|object} values Register-indexed source values.
|
|
324
|
-
* @param {Function} Constructor Entry constructor exposing `from`.
|
|
325
|
-
* @param {object} options Hydration options passed to entry construction.
|
|
326
|
-
* @param {string} field Diagnostic field name.
|
|
327
|
-
* @returns {Map<number, *>} Canonical register map.
|
|
362
|
+
/**
|
|
363
|
+
* Normalize one register-indexed collection into its canonical typed map.
|
|
364
|
+
*
|
|
365
|
+
* @param {Map|object} values Register-indexed source values.
|
|
366
|
+
* @param {Function} Constructor Entry constructor exposing `from`.
|
|
367
|
+
* @param {object} options Hydration options passed to entry construction.
|
|
368
|
+
* @param {string} field Diagnostic field name.
|
|
369
|
+
* @returns {Map<number, *>} Canonical register map.
|
|
328
370
|
*/
|
|
329
371
|
static readCanonicalRegisterMap(values, Constructor, options, field) {
|
|
330
372
|
const entries = values instanceof Map ? values : Object.entries(values ?? {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tr2EffectStageInput.js","sources":["../../../../../src/resource/shader/reflection/Tr2EffectStageInput.js"],"sourcesContent":["// Source: trinity/trinity/Shader/Tr2EffectDescription.h\n// Source: trinity/trinity/Shader/Tr2EffectDescription.cpp\nimport { CjsSchema, impl, type } from \"@carbonenginejs/runtime-utils/schema\";\nimport { CjsModel } from \"@carbonenginejs/runtime-utils/model\";\nimport { copyBytes } from \"@carbonenginejs/runtime-utils/bytes\";\nimport {\n isPlainObject,\n isUint32\n} from \"@carbonenginejs/runtime-utils/is\";\nimport { Tr2SamplerSetup } from \"../sampler/Tr2SamplerSetup.js\";\nimport { Tr2EffectConstant } from \"./Tr2EffectConstant.js\";\nimport { Tr2EffectParameterAnnotation } from \"./Tr2EffectParameterAnnotation.js\";\nimport { Tr2EffectResource } from \"./Tr2EffectResource.js\";\nimport {\n recordBytes,\n recordRawBits,\n toRecordBlob,\n toRecordFloat,\n toRecordText\n} from \"./carbonRecordFields.js\";\nimport { compareUtf8 } from \"../../../format/compareUtf8.js\";\nimport { requireShaderStageType } from \"./shaderStage.js\";\n\n/**\n * The offset word a zero-size blob carries, or the null sentinel.\n *\n * @param {{size:number,offset:number}} ref Blob reference.\n * @returns {number} Offset word worth retaining.\n */\nfunction unsetOffsetOf(ref)\n{\n return ref.size === 0 ? ref.offset : 0xffffffff;\n}\n\n/** Complete device-free reflection for one shader stage input. */\nexport class Tr2EffectStageInput extends CjsModel\n{\n\n /** Portable stage index; Carbon otherwise implies this from the containing array. */\n stageType = -1;\n\n /** m_exists (bool) */\n exists = false;\n\n /** resources (Tr2EffectResourceMap) */\n resources = new Map();\n\n /** uavs (Tr2EffectResourceMap) */\n uavs = new Map();\n\n /** samplers (Tr2SamplerSetupMap) */\n samplers = new Map();\n\n /** m_shader (unsigned) */\n shader = 0xffffffff;\n\n /** constants (Tr2EffectConstantVector) */\n constants = [];\n\n /** m_constantValueSize (unsigned) */\n constantValueSize = 0;\n\n /** constantValues (char[SHADER_CONSTANTS_MAX]) */\n constantValues = new Uint8Array(0);\n\n /** signature (Tr2ShaderSignatureAL) */\n signature = null;\n\n /** annotation (Tr2EffectParameterAnnotationMap) */\n annotation = [];\n\n /** Exact source program metadata and owned bytes, before backend realization. */\n sourceProgram = null;\n\n /**\n * Construct one canonical stage input from JS/JSON model values.\n *\n * @param {object} values Canonical model values.\n * @param {object} options CjsModel import options.\n * @returns {Tr2EffectStageInput} Hydrated stage input.\n */\n static from(values = {}, options = {})\n {\n let normalized = values;\n const maps = new Map();\n for (const [ field, Constructor ] of [\n [ \"resources\", Tr2EffectResource ],\n [ \"uavs\", Tr2EffectResource ],\n [ \"samplers\", Tr2SamplerSetup ]\n ])\n {\n if (values && Object.hasOwn(values, field))\n {\n normalized = normalized === values ? { ...values } : normalized;\n normalized[field] = this.readCanonicalRegisterMap(\n values[field],\n Constructor,\n options,\n field\n );\n maps.set(field, normalized[field]);\n }\n }\n const stage = super.from(normalized, options);\n for (const [ field, value ] of maps)\n {\n stage[field] = value;\n }\n return stage;\n }\n\n /**\n * Hydrate one canonical stage input from a decoded Carbon binary record.\n *\n * @param {object} record Decoded Carbon stage record.\n * @returns {Tr2EffectStageInput} Hydrated canonical stage input.\n */\n static fromCarbonBinary(record)\n {\n if (!isPlainObject(record))\n {\n throw new TypeError(\"Carbon effect stage record must be an object\");\n }\n\n const input = this.fromCarbonBinaryInput(record, record.type);\n input.signature.pipelineInputCount = record.pipelineInputs.length;\n input.signature.pipelineInputs = record.pipelineInputs.map(entry => ({\n usage: entry.usage,\n registerIndex: entry.registerIndex,\n usageIndex: entry.usageIndex,\n usedMask: entry.usedMask,\n type: entry.type,\n dimension: entry.dimension\n }));\n input.signature.threadGroupSize = {\n x: record.threadGroupSize[0],\n y: record.threadGroupSize[1],\n z: record.threadGroupSize[2]\n };\n input.sourceProgram = {\n kind: \"stage\",\n bytes: copyBytes(recordBytes(record.shaderData)),\n shaderSize: record.shaderData.size,\n // Meaningful only at size zero, where the writer passes the word through\n // rather than interning. At any other size it is a live arena offset that\n // belongs to the container it was read from, so it is not retained.\n unsetOffset: unsetOffsetOf(record.shaderData)\n };\n return input;\n }\n\n /**\n * Build one stage input from a Carbon v15 `StageData` block.\n *\n * A raytracing library's global and local inputs are the same block without a\n * stage wrapper — no stage type, no pipeline inputs, no thread group, no\n * program of their own — so this is the half both callers share and\n * `fromCarbonBinary` is the stage-only remainder layered on top.\n *\n * Carbon writes textures, samplers and UAVs in ascending register order because\n * they are `std::map`s, and they are re-keyed by register here rather than by\n * position, so the map is authoritative and the record's order is not load\n * bearing.\n *\n * @param {object} record Carbon stage-data record.\n * @param {number} [stageType] Stage index, or -1 for a library input.\n * @returns {Tr2EffectStageInput} Reflected stage input.\n */\n static fromCarbonBinaryInput(record, stageType = -1)\n {\n if (!isPlainObject(record))\n {\n throw new TypeError(\"Carbon effect stage-data record must be an object\");\n }\n\n const constantValues = copyBytes(recordBytes(record.defaultValues));\n\n const input = new this();\n input.stageType = stageType;\n input.exists = true;\n input.constants = record.constants.map(\n entry => Tr2EffectConstant.fromCarbonBinary(entry)\n );\n input.resources = this.readCarbonBinaryResourceMap(record.textures);\n input.uavs = this.readCarbonBinaryResourceMap(record.uavs);\n input.samplers = this.readCarbonBinarySamplerMap(record.samplers);\n input.constantValueSize = constantValues.byteLength;\n input.constantValues = constantValues;\n input.constantValuesUnsetOffset = unsetOffsetOf(record.defaultValues);\n input.annotation = record.annotations.map(\n entry => Tr2EffectParameterAnnotation.fromCarbonBinary(entry)\n );\n input.signature = {\n pipelineInputCount: 0,\n pipelineInputs: [],\n registerCount: record.registers.length,\n // Carbon stores one field its reader calls `arrayCount` and its writer\n // calls `registerCount`. Both names are carried forward from the single\n // stored value, because the write direction refuses to emit a record whose\n // two names disagree.\n registers: record.registers.map(entry => ({\n registerType: entry.registerType,\n registerIndex: entry.registerIndex,\n arrayCount: entry.registerCount,\n registerCount: entry.registerCount,\n registerSpace: entry.registerSpace\n })),\n staticSamplerCount: record.staticSamplers.length,\n staticSamplers: record.staticSamplers.map(entry => ({\n registerIndex: entry.registerIndex,\n registerSpace: entry.registerSpace,\n descriptor: {\n comparison: !!entry.comparison,\n minFilter: entry.minFilter,\n magFilter: entry.magFilter,\n mipFilter: entry.mipFilter,\n addressU: entry.addressU,\n addressV: entry.addressV,\n addressW: entry.addressW,\n mipLODBiasRaw: recordRawBits(entry.mipLODBias),\n maxAnisotropy: entry.maxAnisotropy,\n comparisonFunc: entry.comparisonFunc,\n // A static sampler's border colour is a one-byte enum, not four\n // floats. Sharing the dynamic sampler's mapping here would silently\n // reinterpret it.\n borderColor: entry.borderColor,\n minLODRaw: recordRawBits(entry.minLOD),\n maxLODRaw: recordRawBits(entry.maxLOD)\n }\n })),\n threadGroupSize: { x: 0, y: 0, z: 0 }\n };\n input.sourceProgram = null;\n return input;\n }\n\n /**\n * Emit this stage as a Carbon v15 stage record.\n *\n * @returns {object} Carbon stage record.\n */\n toCarbonBinary()\n {\n const signature = this.signature ?? {};\n const program = this.sourceProgram ?? {};\n return {\n type: this.stageType,\n shaderData: toRecordBlob(\n program.bytes,\n program.shaderSize,\n program.unsetOffset\n ),\n threadGroupSize: [\n signature.threadGroupSize?.x ?? 0,\n signature.threadGroupSize?.y ?? 0,\n signature.threadGroupSize?.z ?? 0\n ],\n pipelineInputs: (signature.pipelineInputs ?? []).map(entry => ({\n usage: entry.usage,\n registerIndex: entry.registerIndex,\n usageIndex: entry.usageIndex,\n usedMask: entry.usedMask,\n type: entry.type,\n dimension: entry.dimension\n })),\n ...this.toCarbonBinaryInput()\n };\n }\n\n /**\n * Emit this input as a Carbon v15 `StageData` block.\n *\n * Carbon holds textures, samplers, UAVs and render states in `std::map`s and\n * writes them in key order, and it sorts annotation names by `strcmp` before\n * writing. Our maps are keyed but not ordered, so every collection is sorted\n * explicitly here rather than trusting insertion order — the reader is\n * indifferent, but the bytes are not, and a container that disagrees with\n * Carbon's ordering is not the file Carbon would have written.\n *\n * @returns {object} Carbon stage-data record.\n */\n toCarbonBinaryInput()\n {\n const byRegister = (left, right) => left.registerIndex - right.registerIndex;\n const signature = this.signature ?? {};\n return {\n registers: (signature.registers ?? []).map(entry => ({\n registerType: entry.registerType,\n registerIndex: entry.registerIndex,\n registerCount: entry.registerCount,\n registerSpace: entry.registerSpace\n })),\n staticSamplers: (signature.staticSamplers ?? []).map(entry =>\n {\n const descriptor = entry.descriptor ?? {};\n return {\n registerIndex: entry.registerIndex,\n registerSpace: entry.registerSpace,\n comparison: descriptor.comparison ? 1 : 0,\n minFilter: descriptor.minFilter,\n magFilter: descriptor.magFilter,\n mipFilter: descriptor.mipFilter,\n addressU: descriptor.addressU,\n addressV: descriptor.addressV,\n addressW: descriptor.addressW,\n mipLODBias: toRecordFloat(descriptor.mipLODBiasRaw),\n maxAnisotropy: descriptor.maxAnisotropy,\n comparisonFunc: descriptor.comparisonFunc,\n // One byte here, four floats on a dynamic sampler.\n borderColor: descriptor.borderColor,\n minLOD: toRecordFloat(descriptor.minLODRaw),\n maxLOD: toRecordFloat(descriptor.maxLODRaw)\n };\n }),\n constants: this.constants.map(constant => constant.toCarbonBinary()),\n defaultValues: toRecordBlob(\n this.constantValues,\n this.constantValueSize,\n this.constantValuesUnsetOffset\n ),\n textures: Array.from(this.resources, ([ register, resource ]) =>\n resource.toCarbonBinary(register)).sort(byRegister),\n samplers: Array.from(this.samplers, ([ register, sampler ]) =>\n sampler.toCarbonBinary(register)).sort(byRegister),\n uavs: Array.from(this.uavs, ([ register, uav ]) =>\n uav.toCarbonBinary(register, true)).sort(byRegister),\n annotations: this.annotation\n .map(entry => entry.toCarbonBinary())\n .sort((left, right) => compareUtf8(left.name.value, right.name.value))\n };\n }\n\n /** Build one register-indexed resource map from Carbon texture or UAV records. */\n static readCarbonBinaryResourceMap(records)\n {\n const result = new Map();\n for (const record of records)\n {\n if (result.has(record.registerIndex))\n {\n throw new Error(\n `Carbon effect resource register ${record.registerIndex} is duplicated`\n );\n }\n result.set(\n record.registerIndex,\n Tr2EffectResource.fromCarbonBinary(record)\n );\n }\n return result;\n }\n\n /** Build one register-indexed sampler map from Carbon sampler records. */\n static readCarbonBinarySamplerMap(records)\n {\n const result = new Map();\n for (const record of records)\n {\n if (result.has(record.registerIndex))\n {\n throw new Error(\n `Carbon effect sampler register ${record.registerIndex} is duplicated`\n );\n }\n result.set(\n record.registerIndex,\n Tr2SamplerSetup.fromCarbonBinary(record)\n );\n }\n return result;\n }\n\n /**\n * Create one explicit absent stage slot.\n *\n * @param {number} stageType Stage index.\n * @returns {Tr2EffectStageInput} Empty stage input.\n */\n static createEmpty(stageType)\n {\n const stage = new this();\n stage.stageType = requireShaderStageType(stageType);\n return stage;\n }\n\n /**\n * Normalize one register-indexed collection into its canonical typed map.\n *\n * @param {Map|object} values Register-indexed source values.\n * @param {Function} Constructor Entry constructor exposing `from`.\n * @param {object} options Hydration options passed to entry construction.\n * @param {string} field Diagnostic field name.\n * @returns {Map<number, *>} Canonical register map.\n */\n static readCanonicalRegisterMap(values, Constructor, options, field)\n {\n const entries = values instanceof Map\n ? values\n : Object.entries(values ?? {});\n const result = new Map();\n for (const [ key, value ] of entries)\n {\n const registerIndex = Number(key);\n if (!isUint32(registerIndex))\n {\n throw new RangeError(\n `Effect ${field} register index must fit uint32`\n );\n }\n if (result.has(registerIndex))\n {\n throw new Error(\n `Effect ${field} register ${registerIndex} is duplicated`\n );\n }\n result.set(\n registerIndex,\n value instanceof Constructor\n ? value\n : Constructor.from(value, options)\n );\n }\n return result;\n }\n\n}\n\n// Declared imperatively rather than with decorators, so this module stays\n// plain ESM that loads from source without a transform. The decorator\n// expressions are reused verbatim, so the registered metadata is identical.\n// Statics belong in `methods`: decorateMethod targets the prototype and\n// would register a static as an instance field.\nCjsSchema.define(Tr2EffectStageInput, {\n className: \"Tr2EffectStageInput\",\n family: \"shader\",\n fields: {\n stageType: [ impl.adapted, impl.reason(\"The source format identifies stage inputs by array index; the device-free graph retains the index explicitly for serialization and engine adapters.\"), type.int32 ],\n exists: type.boolean,\n resources: type.map(\"Tr2EffectResource\"),\n uavs: type.map(\"Tr2EffectResource\"),\n samplers: type.map(\"Tr2SamplerSetup\"),\n shader: type.uint32,\n constants: type.list(\"Tr2EffectConstant\"),\n constantValueSize: type.uint32,\n constantValues: type.typedArray(\"Uint8Array\"),\n constantValuesUnsetOffset: [ impl.custom, impl.reason(\"A zero-size blob's offset word is passed through rather than interned, and the shipped corpus does not always set it to the null sentinel; the graph retains it so a body re-emits as the file that produced it.\"), type.uint32 ],\n signature: type.rawStruct(\"Tr2ShaderSignatureAL\"),\n annotation: type.list(\"Tr2EffectParameterAnnotation\"),\n sourceProgram: [ impl.adapted, impl.reason(\"Carbon replaces source program data with renderer handles while reading; the device-free resource graph must retain the portable source program for later engine realization.\"), type.rawStruct(\"CjsEffectSourceProgram\") ]\n }\n});\n"],"names":["unsetOffsetOf","ref","size","offset","Tr2EffectStageInput","CjsModel","stageType","exists","resources","Map","uavs","samplers","shader","constants","constantValueSize","constantValues","Uint8Array","signature","annotation","sourceProgram","from","values","options","normalized","maps","field","Constructor","Tr2EffectResource","Tr2SamplerSetup","Object","hasOwn","readCanonicalRegisterMap","set","stage","value","fromCarbonBinary","record","isPlainObject","TypeError","input","fromCarbonBinaryInput","type","pipelineInputCount","pipelineInputs","length","map","entry","usage","registerIndex","usageIndex","usedMask","dimension","threadGroupSize","x","y","z","kind","bytes","copyBytes","recordBytes","shaderData","shaderSize","unsetOffset","defaultValues","Tr2EffectConstant","readCarbonBinaryResourceMap","textures","readCarbonBinarySamplerMap","byteLength","constantValuesUnsetOffset","annotations","Tr2EffectParameterAnnotation","registerCount","registers","registerType","arrayCount","registerSpace","staticSamplerCount","staticSamplers","descriptor","comparison","minFilter","magFilter","mipFilter","addressU","addressV","addressW","mipLODBiasRaw","recordRawBits","mipLODBias","maxAnisotropy","comparisonFunc","borderColor","minLODRaw","minLOD","maxLODRaw","maxLOD","toCarbonBinary","program","toRecordBlob","toCarbonBinaryInput","byRegister","left","right","toRecordFloat","constant","Array","register","resource","sort","sampler","uav","compareUtf8","name","records","result","has","Error","createEmpty","requireShaderStageType","entries","key","Number","isUint32","RangeError","CjsSchema","define","className","family","fields","impl","adapted","reason","int32","boolean","uint32","list","typedArray","custom","rawStruct"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tr2EffectStageInput.js","sources":["../../../../../src/resource/shader/reflection/Tr2EffectStageInput.js"],"sourcesContent":["// Source: trinity/trinity/Shader/Tr2EffectDescription.h\r\n// Source: trinity/trinity/Shader/Tr2EffectDescription.cpp\r\nimport { CjsSchema, impl, type } from \"@carbonenginejs/runtime-utils/schema\";\r\nimport { CjsModel } from \"@carbonenginejs/runtime-utils/model\";\r\nimport { copyBytes } from \"@carbonenginejs/runtime-utils/bytes\";\r\nimport {\r\n isPlainObject,\r\n isUint32\r\n} from \"@carbonenginejs/runtime-utils/is\";\r\nimport { Tr2SamplerSetup } from \"../sampler/Tr2SamplerSetup.js\";\r\nimport { Tr2EffectConstant } from \"./Tr2EffectConstant.js\";\r\nimport { Tr2EffectParameterAnnotation } from \"./Tr2EffectParameterAnnotation.js\";\r\nimport { Tr2EffectResource } from \"./Tr2EffectResource.js\";\r\nimport {\r\n recordBytes,\r\n recordRawBits,\r\n toRecordBlob,\r\n toRecordFloat,\r\n toRecordText\r\n} from \"./carbonRecordFields.js\";\r\nimport { compareUtf8 } from \"../../../format/compareUtf8.js\";\r\nimport { requireShaderStageType } from \"./shaderStage.js\";\r\n\r\n/**\r\n * The offset word a zero-size blob carries, or the null sentinel.\r\n *\r\n * @param {{size:number,offset:number}} ref Blob reference.\r\n * @returns {number} Offset word worth retaining.\r\n */\r\nfunction unsetOffsetOf(ref)\r\n{\r\n return ref.size === 0 ? ref.offset : 0xffffffff;\r\n}\r\n\r\n/** Complete device-free reflection for one shader stage input. */\r\nexport class Tr2EffectStageInput extends CjsModel\r\n{\r\n\r\n /** Portable stage index; Carbon otherwise implies this from the containing array. */\r\n stageType = -1;\r\n\r\n /** m_exists (bool) */\r\n exists = false;\r\n\r\n /** resources (Tr2EffectResourceMap) */\r\n resources = new Map();\r\n\r\n /** uavs (Tr2EffectResourceMap) */\r\n uavs = new Map();\r\n\r\n /** samplers (Tr2SamplerSetupMap) */\r\n samplers = new Map();\r\n\r\n /** m_shader (unsigned) */\r\n shader = 0xffffffff;\r\n\r\n /** constants (Tr2EffectConstantVector) */\r\n constants = [];\r\n\r\n /** m_constantValueSize (unsigned) */\r\n constantValueSize = 0;\r\n\r\n /** constantValues (char[SHADER_CONSTANTS_MAX]) */\r\n constantValues = new Uint8Array(0);\r\n\r\n /** signature (Tr2ShaderSignatureAL) */\r\n signature = null;\r\n\r\n /** annotation (Tr2EffectParameterAnnotationMap) */\r\n annotation = [];\r\n\r\n /** Exact source program metadata and owned bytes, before backend realization. */\r\n sourceProgram = null;\r\n\r\n // Ported from CarbonEngine (MIT, (c) 2026 CCP Games) - https://github.com/carbonengine/trinity\r\n // trinity/Shader/Tr2Effect.cpp:1799-1821 (the sizing loop and its assertion)\r\n //\r\n // Carbon's comment at the site is the whole rule: \"Figure out how large the\r\n // constant buffer has to be. This has to be done even if the constant isn't\r\n // set, as the shader may still sample it and expect to get some kind of\r\n // default (usually zero).\" So EVERY constant participates, not only the ones\r\n // an effect binds a parameter to.\r\n //\r\n // THIS IS NOT `constantValueSize`, AND THE DIFFERENCE IS EASY TO MISS.\r\n // `constantValueSize` is the length of the authored DEFAULT blob, which\r\n // Carbon separately grows to cover autoregister sampler-index constants\r\n // (Tr2EffectDescription.cpp:629-632). Carbon asserts\r\n // `constantSize >= constantDefaultValueSize` precisely because the two are\r\n // different numbers and the defaults are a PREFIX of the buffer. An effect\r\n // that authors defaults for only some of its constants makes them differ, so\r\n // using the default size as the buffer size is right until it silently is\r\n // not.\r\n //\r\n // It lives here rather than in a consumer because it is arithmetic over this\r\n // object's own constants and gives every backend the same answer. A backend\r\n // then applies its own alignment on top - WebGPU's uniform binding alignment,\r\n // std140 for a WebGL2 block - and that padding is the backend's, not this.\r\n // Decision 4 of the engine backends plan names the alternative as a defect\r\n // worth declining to inherit: Carbon replicates its draw-argument arithmetic\r\n // across ten call sites, and this would replicate the same way once a second\r\n // engine exists.\r\n\r\n /**\r\n * The byte size a constant buffer must have to hold every declared constant.\r\n *\r\n * Always at least `constantValueSize`, because the authored defaults occupy\r\n * the start of the same buffer.\r\n */\r\n GetConstantBufferSize()\r\n {\r\n let size = 0;\r\n\r\n for (const constant of this.constants)\r\n {\r\n size = Math.max(size, (constant?.offset ?? 0) + (constant?.size ?? 0));\r\n }\r\n\r\n return Math.max(size, this.constantValueSize);\r\n }\r\n\r\n /**\r\n * Construct one canonical stage input from JS/JSON model values.\r\n *\r\n * @param {object} values Canonical model values.\r\n * @param {object} options CjsModel import options.\r\n * @returns {Tr2EffectStageInput} Hydrated stage input.\r\n */\r\n static from(values = {}, options = {})\r\n {\r\n let normalized = values;\r\n const maps = new Map();\r\n for (const [ field, Constructor ] of [\r\n [ \"resources\", Tr2EffectResource ],\r\n [ \"uavs\", Tr2EffectResource ],\r\n [ \"samplers\", Tr2SamplerSetup ]\r\n ])\r\n {\r\n if (values && Object.hasOwn(values, field))\r\n {\r\n normalized = normalized === values ? { ...values } : normalized;\r\n normalized[field] = this.readCanonicalRegisterMap(\r\n values[field],\r\n Constructor,\r\n options,\r\n field\r\n );\r\n maps.set(field, normalized[field]);\r\n }\r\n }\r\n const stage = super.from(normalized, options);\r\n for (const [ field, value ] of maps)\r\n {\r\n stage[field] = value;\r\n }\r\n return stage;\r\n }\r\n\r\n /**\r\n * Hydrate one canonical stage input from a decoded Carbon binary record.\r\n *\r\n * @param {object} record Decoded Carbon stage record.\r\n * @returns {Tr2EffectStageInput} Hydrated canonical stage input.\r\n */\r\n static fromCarbonBinary(record)\r\n {\r\n if (!isPlainObject(record))\r\n {\r\n throw new TypeError(\"Carbon effect stage record must be an object\");\r\n }\r\n\r\n const input = this.fromCarbonBinaryInput(record, record.type);\r\n input.signature.pipelineInputCount = record.pipelineInputs.length;\r\n input.signature.pipelineInputs = record.pipelineInputs.map(entry => ({\r\n usage: entry.usage,\r\n registerIndex: entry.registerIndex,\r\n usageIndex: entry.usageIndex,\r\n usedMask: entry.usedMask,\r\n type: entry.type,\r\n dimension: entry.dimension\r\n }));\r\n input.signature.threadGroupSize = {\r\n x: record.threadGroupSize[0],\r\n y: record.threadGroupSize[1],\r\n z: record.threadGroupSize[2]\r\n };\r\n input.sourceProgram = {\r\n kind: \"stage\",\r\n bytes: copyBytes(recordBytes(record.shaderData)),\r\n shaderSize: record.shaderData.size,\r\n // Meaningful only at size zero, where the writer passes the word through\r\n // rather than interning. At any other size it is a live arena offset that\r\n // belongs to the container it was read from, so it is not retained.\r\n unsetOffset: unsetOffsetOf(record.shaderData)\r\n };\r\n return input;\r\n }\r\n\r\n /**\r\n * Build one stage input from a Carbon v15 `StageData` block.\r\n *\r\n * A raytracing library's global and local inputs are the same block without a\r\n * stage wrapper — no stage type, no pipeline inputs, no thread group, no\r\n * program of their own — so this is the half both callers share and\r\n * `fromCarbonBinary` is the stage-only remainder layered on top.\r\n *\r\n * Carbon writes textures, samplers and UAVs in ascending register order because\r\n * they are `std::map`s, and they are re-keyed by register here rather than by\r\n * position, so the map is authoritative and the record's order is not load\r\n * bearing.\r\n *\r\n * @param {object} record Carbon stage-data record.\r\n * @param {number} [stageType] Stage index, or -1 for a library input.\r\n * @returns {Tr2EffectStageInput} Reflected stage input.\r\n */\r\n static fromCarbonBinaryInput(record, stageType = -1)\r\n {\r\n if (!isPlainObject(record))\r\n {\r\n throw new TypeError(\"Carbon effect stage-data record must be an object\");\r\n }\r\n\r\n const constantValues = copyBytes(recordBytes(record.defaultValues));\r\n\r\n const input = new this();\r\n input.stageType = stageType;\r\n input.exists = true;\r\n input.constants = record.constants.map(\r\n entry => Tr2EffectConstant.fromCarbonBinary(entry)\r\n );\r\n input.resources = this.readCarbonBinaryResourceMap(record.textures);\r\n input.uavs = this.readCarbonBinaryResourceMap(record.uavs);\r\n input.samplers = this.readCarbonBinarySamplerMap(record.samplers);\r\n input.constantValueSize = constantValues.byteLength;\r\n input.constantValues = constantValues;\r\n input.constantValuesUnsetOffset = unsetOffsetOf(record.defaultValues);\r\n input.annotation = record.annotations.map(\r\n entry => Tr2EffectParameterAnnotation.fromCarbonBinary(entry)\r\n );\r\n input.signature = {\r\n pipelineInputCount: 0,\r\n pipelineInputs: [],\r\n registerCount: record.registers.length,\r\n // Carbon stores one field its reader calls `arrayCount` and its writer\r\n // calls `registerCount`. Both names are carried forward from the single\r\n // stored value, because the write direction refuses to emit a record whose\r\n // two names disagree.\r\n registers: record.registers.map(entry => ({\r\n registerType: entry.registerType,\r\n registerIndex: entry.registerIndex,\r\n arrayCount: entry.registerCount,\r\n registerCount: entry.registerCount,\r\n registerSpace: entry.registerSpace\r\n })),\r\n staticSamplerCount: record.staticSamplers.length,\r\n staticSamplers: record.staticSamplers.map(entry => ({\r\n registerIndex: entry.registerIndex,\r\n registerSpace: entry.registerSpace,\r\n descriptor: {\r\n comparison: !!entry.comparison,\r\n minFilter: entry.minFilter,\r\n magFilter: entry.magFilter,\r\n mipFilter: entry.mipFilter,\r\n addressU: entry.addressU,\r\n addressV: entry.addressV,\r\n addressW: entry.addressW,\r\n mipLODBiasRaw: recordRawBits(entry.mipLODBias),\r\n maxAnisotropy: entry.maxAnisotropy,\r\n comparisonFunc: entry.comparisonFunc,\r\n // A static sampler's border colour is a one-byte enum, not four\r\n // floats. Sharing the dynamic sampler's mapping here would silently\r\n // reinterpret it.\r\n borderColor: entry.borderColor,\r\n minLODRaw: recordRawBits(entry.minLOD),\r\n maxLODRaw: recordRawBits(entry.maxLOD)\r\n }\r\n })),\r\n threadGroupSize: { x: 0, y: 0, z: 0 }\r\n };\r\n input.sourceProgram = null;\r\n return input;\r\n }\r\n\r\n /**\r\n * Emit this stage as a Carbon v15 stage record.\r\n *\r\n * @returns {object} Carbon stage record.\r\n */\r\n toCarbonBinary()\r\n {\r\n const signature = this.signature ?? {};\r\n const program = this.sourceProgram ?? {};\r\n return {\r\n type: this.stageType,\r\n shaderData: toRecordBlob(\r\n program.bytes,\r\n program.shaderSize,\r\n program.unsetOffset\r\n ),\r\n threadGroupSize: [\r\n signature.threadGroupSize?.x ?? 0,\r\n signature.threadGroupSize?.y ?? 0,\r\n signature.threadGroupSize?.z ?? 0\r\n ],\r\n pipelineInputs: (signature.pipelineInputs ?? []).map(entry => ({\r\n usage: entry.usage,\r\n registerIndex: entry.registerIndex,\r\n usageIndex: entry.usageIndex,\r\n usedMask: entry.usedMask,\r\n type: entry.type,\r\n dimension: entry.dimension\r\n })),\r\n ...this.toCarbonBinaryInput()\r\n };\r\n }\r\n\r\n /**\r\n * Emit this input as a Carbon v15 `StageData` block.\r\n *\r\n * Carbon holds textures, samplers, UAVs and render states in `std::map`s and\r\n * writes them in key order, and it sorts annotation names by `strcmp` before\r\n * writing. Our maps are keyed but not ordered, so every collection is sorted\r\n * explicitly here rather than trusting insertion order — the reader is\r\n * indifferent, but the bytes are not, and a container that disagrees with\r\n * Carbon's ordering is not the file Carbon would have written.\r\n *\r\n * @returns {object} Carbon stage-data record.\r\n */\r\n toCarbonBinaryInput()\r\n {\r\n const byRegister = (left, right) => left.registerIndex - right.registerIndex;\r\n const signature = this.signature ?? {};\r\n return {\r\n registers: (signature.registers ?? []).map(entry => ({\r\n registerType: entry.registerType,\r\n registerIndex: entry.registerIndex,\r\n registerCount: entry.registerCount,\r\n registerSpace: entry.registerSpace\r\n })),\r\n staticSamplers: (signature.staticSamplers ?? []).map(entry =>\r\n {\r\n const descriptor = entry.descriptor ?? {};\r\n return {\r\n registerIndex: entry.registerIndex,\r\n registerSpace: entry.registerSpace,\r\n comparison: descriptor.comparison ? 1 : 0,\r\n minFilter: descriptor.minFilter,\r\n magFilter: descriptor.magFilter,\r\n mipFilter: descriptor.mipFilter,\r\n addressU: descriptor.addressU,\r\n addressV: descriptor.addressV,\r\n addressW: descriptor.addressW,\r\n mipLODBias: toRecordFloat(descriptor.mipLODBiasRaw),\r\n maxAnisotropy: descriptor.maxAnisotropy,\r\n comparisonFunc: descriptor.comparisonFunc,\r\n // One byte here, four floats on a dynamic sampler.\r\n borderColor: descriptor.borderColor,\r\n minLOD: toRecordFloat(descriptor.minLODRaw),\r\n maxLOD: toRecordFloat(descriptor.maxLODRaw)\r\n };\r\n }),\r\n constants: this.constants.map(constant => constant.toCarbonBinary()),\r\n defaultValues: toRecordBlob(\r\n this.constantValues,\r\n this.constantValueSize,\r\n this.constantValuesUnsetOffset\r\n ),\r\n textures: Array.from(this.resources, ([ register, resource ]) =>\r\n resource.toCarbonBinary(register)).sort(byRegister),\r\n samplers: Array.from(this.samplers, ([ register, sampler ]) =>\r\n sampler.toCarbonBinary(register)).sort(byRegister),\r\n uavs: Array.from(this.uavs, ([ register, uav ]) =>\r\n uav.toCarbonBinary(register, true)).sort(byRegister),\r\n annotations: this.annotation\r\n .map(entry => entry.toCarbonBinary())\r\n .sort((left, right) => compareUtf8(left.name.value, right.name.value))\r\n };\r\n }\r\n\r\n /** Build one register-indexed resource map from Carbon texture or UAV records. */\r\n static readCarbonBinaryResourceMap(records)\r\n {\r\n const result = new Map();\r\n for (const record of records)\r\n {\r\n if (result.has(record.registerIndex))\r\n {\r\n throw new Error(\r\n `Carbon effect resource register ${record.registerIndex} is duplicated`\r\n );\r\n }\r\n result.set(\r\n record.registerIndex,\r\n Tr2EffectResource.fromCarbonBinary(record)\r\n );\r\n }\r\n return result;\r\n }\r\n\r\n /** Build one register-indexed sampler map from Carbon sampler records. */\r\n static readCarbonBinarySamplerMap(records)\r\n {\r\n const result = new Map();\r\n for (const record of records)\r\n {\r\n if (result.has(record.registerIndex))\r\n {\r\n throw new Error(\r\n `Carbon effect sampler register ${record.registerIndex} is duplicated`\r\n );\r\n }\r\n result.set(\r\n record.registerIndex,\r\n Tr2SamplerSetup.fromCarbonBinary(record)\r\n );\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Create one explicit absent stage slot.\r\n *\r\n * @param {number} stageType Stage index.\r\n * @returns {Tr2EffectStageInput} Empty stage input.\r\n */\r\n static createEmpty(stageType)\r\n {\r\n const stage = new this();\r\n stage.stageType = requireShaderStageType(stageType);\r\n return stage;\r\n }\r\n\r\n /**\r\n * Normalize one register-indexed collection into its canonical typed map.\r\n *\r\n * @param {Map|object} values Register-indexed source values.\r\n * @param {Function} Constructor Entry constructor exposing `from`.\r\n * @param {object} options Hydration options passed to entry construction.\r\n * @param {string} field Diagnostic field name.\r\n * @returns {Map<number, *>} Canonical register map.\r\n */\r\n static readCanonicalRegisterMap(values, Constructor, options, field)\r\n {\r\n const entries = values instanceof Map\r\n ? values\r\n : Object.entries(values ?? {});\r\n const result = new Map();\r\n for (const [ key, value ] of entries)\r\n {\r\n const registerIndex = Number(key);\r\n if (!isUint32(registerIndex))\r\n {\r\n throw new RangeError(\r\n `Effect ${field} register index must fit uint32`\r\n );\r\n }\r\n if (result.has(registerIndex))\r\n {\r\n throw new Error(\r\n `Effect ${field} register ${registerIndex} is duplicated`\r\n );\r\n }\r\n result.set(\r\n registerIndex,\r\n value instanceof Constructor\r\n ? value\r\n : Constructor.from(value, options)\r\n );\r\n }\r\n return result;\r\n }\r\n\r\n}\r\n\r\n// Declared imperatively rather than with decorators, so this module stays\r\n// plain ESM that loads from source without a transform. The decorator\r\n// expressions are reused verbatim, so the registered metadata is identical.\r\n// Statics belong in `methods`: decorateMethod targets the prototype and\r\n// would register a static as an instance field.\r\nCjsSchema.define(Tr2EffectStageInput, {\r\n className: \"Tr2EffectStageInput\",\r\n family: \"shader\",\r\n fields: {\r\n stageType: [ impl.adapted, impl.reason(\"The source format identifies stage inputs by array index; the device-free graph retains the index explicitly for serialization and engine adapters.\"), type.int32 ],\r\n exists: type.boolean,\r\n resources: type.map(\"Tr2EffectResource\"),\r\n uavs: type.map(\"Tr2EffectResource\"),\r\n samplers: type.map(\"Tr2SamplerSetup\"),\r\n shader: type.uint32,\r\n constants: type.list(\"Tr2EffectConstant\"),\r\n constantValueSize: type.uint32,\r\n constantValues: type.typedArray(\"Uint8Array\"),\r\n constantValuesUnsetOffset: [ impl.custom, impl.reason(\"A zero-size blob's offset word is passed through rather than interned, and the shipped corpus does not always set it to the null sentinel; the graph retains it so a body re-emits as the file that produced it.\"), type.uint32 ],\r\n signature: type.rawStruct(\"Tr2ShaderSignatureAL\"),\r\n annotation: type.list(\"Tr2EffectParameterAnnotation\"),\r\n sourceProgram: [ impl.adapted, impl.reason(\"Carbon replaces source program data with renderer handles while reading; the device-free resource graph must retain the portable source program for later engine realization.\"), type.rawStruct(\"CjsEffectSourceProgram\") ]\r\n }\r\n});\r\n"],"names":["unsetOffsetOf","ref","size","offset","Tr2EffectStageInput","CjsModel","stageType","exists","resources","Map","uavs","samplers","shader","constants","constantValueSize","constantValues","Uint8Array","signature","annotation","sourceProgram","GetConstantBufferSize","constant","Math","max","from","values","options","normalized","maps","field","Constructor","Tr2EffectResource","Tr2SamplerSetup","Object","hasOwn","readCanonicalRegisterMap","set","stage","value","fromCarbonBinary","record","isPlainObject","TypeError","input","fromCarbonBinaryInput","type","pipelineInputCount","pipelineInputs","length","map","entry","usage","registerIndex","usageIndex","usedMask","dimension","threadGroupSize","x","y","z","kind","bytes","copyBytes","recordBytes","shaderData","shaderSize","unsetOffset","defaultValues","Tr2EffectConstant","readCarbonBinaryResourceMap","textures","readCarbonBinarySamplerMap","byteLength","constantValuesUnsetOffset","annotations","Tr2EffectParameterAnnotation","registerCount","registers","registerType","arrayCount","registerSpace","staticSamplerCount","staticSamplers","descriptor","comparison","minFilter","magFilter","mipFilter","addressU","addressV","addressW","mipLODBiasRaw","recordRawBits","mipLODBias","maxAnisotropy","comparisonFunc","borderColor","minLODRaw","minLOD","maxLODRaw","maxLOD","toCarbonBinary","program","toRecordBlob","toCarbonBinaryInput","byRegister","left","right","toRecordFloat","Array","register","resource","sort","sampler","uav","compareUtf8","name","records","result","has","Error","createEmpty","requireShaderStageType","entries","key","Number","isUint32","RangeError","CjsSchema","define","className","family","fields","impl","adapted","reason","int32","boolean","uint32","list","typedArray","custom","rawStruct"],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Format type resolution
|
|
2
|
+
|
|
3
|
+
Status: Evolving
|
|
4
|
+
Scope: `CjsFormat.resolveType`, `CjsResourceProbe`, and the formats that override them
|
|
5
|
+
Audience: Anyone adding a format, choosing a decode route, or debugging a mislabeled container
|
|
6
|
+
Summary: Separates what a container claims about itself from what a reader has evidence it can decode, and states how a verified resolution may and may not change a route.
|
|
7
|
+
|
|
8
|
+
## Claims versus evidence
|
|
9
|
+
|
|
10
|
+
A container's header is a claim. `inspect()` and `isSupported()` report that
|
|
11
|
+
claim: they read the declaration and answer whether this format recognizes it.
|
|
12
|
+
That is the right answer almost always, and it is cheap.
|
|
13
|
+
|
|
14
|
+
`resolveType()` answers a different question — what the reader has *evidence*
|
|
15
|
+
it can actually decode. It performs one bounded asynchronous content check: a
|
|
16
|
+
magic number, a first frame or block, a setup header. It never decodes the
|
|
17
|
+
payload.
|
|
18
|
+
|
|
19
|
+
The distinction matters because a mislabeled container is indistinguishable
|
|
20
|
+
from a correct one until something looks at the content. Routing on the
|
|
21
|
+
declaration alone turns that into a decode failure much later, somewhere that
|
|
22
|
+
has forgotten what the file claimed to be.
|
|
23
|
+
|
|
24
|
+
## The contract
|
|
25
|
+
|
|
26
|
+
`resolveType()` returns a `CjsResourceProbe`. The probe carries a persisted
|
|
27
|
+
`verified` boolean, and its `metadata` carries the evidence: what was
|
|
28
|
+
declared, what resolved, and whether those disagreed. `preferred` names the
|
|
29
|
+
resolved decode route.
|
|
30
|
+
|
|
31
|
+
Three rules govern what a probe may do:
|
|
32
|
+
|
|
33
|
+
- **A caller-forced emit always wins.** Resolution informs a default; it never
|
|
34
|
+
overrides an explicit request.
|
|
35
|
+
- **An unverified result never changes a route.** The base implementation
|
|
36
|
+
delegates to `isSupported()` and sets `verified` to false, so a format
|
|
37
|
+
without an override costs nothing and cannot silently redirect anything.
|
|
38
|
+
- **Opting in is per format.** Overriding is a decision made by a format that
|
|
39
|
+
has a cheap, meaningful content check — not a requirement on all of them.
|
|
40
|
+
|
|
41
|
+
That third rule is why this is a seam rather than a pipeline stage. The
|
|
42
|
+
zero-extra-work path is the default, and it stays free.
|
|
43
|
+
|
|
44
|
+
## What a check may look like: wem
|
|
45
|
+
|
|
46
|
+
`CjsWemFormat` overrides it, and its shape is the model. The `fmt` tag is the
|
|
47
|
+
declaration. Each candidate codec gets one bounded **structural** check
|
|
48
|
+
against container facts — a Wwise Vorbis sidecar present with a positive
|
|
49
|
+
sample count; a PTADPCM frame layout satisfying the decoder's own guard with
|
|
50
|
+
block-aligned data; PCM with self-consistent block alignment and byte rate.
|
|
51
|
+
No audio is decoded in any of them.
|
|
52
|
+
|
|
53
|
+
The declared codec is validated first. Only when its check fails are the other
|
|
54
|
+
candidates tried, in order. The resolved codec maps to an emit — Wwise Vorbis
|
|
55
|
+
to `ogg`, PTADPCM and PCM to `pcm`, anything unresolved to `raw`.
|
|
56
|
+
|
|
57
|
+
A census of all 8,987 embedded wems in one EVE build found no mislabeled tag.
|
|
58
|
+
That is the point rather than a reason to drop the check: it converts a
|
|
59
|
+
corpus-wide assumption into a fact verified per file, and the cost of holding
|
|
60
|
+
that guarantee is one structural read.
|
|
61
|
+
|
|
62
|
+
## Current limits
|
|
63
|
+
|
|
64
|
+
Resolution is available to callers but is **not yet wired into the resource
|
|
65
|
+
read path**. `CjsResMan` still selects a format by extension using the
|
|
66
|
+
synchronous `isSupported()` tie-break, so a mislabeled file routed through
|
|
67
|
+
ordinary resource acquisition is not corrected today. Consumers that need the
|
|
68
|
+
verified answer call `resolveType()` themselves.
|
|
69
|
+
|
|
70
|
+
Wem exposes `raw`, `ogg`, and `pcm` as distinct outputs, so a caller still
|
|
71
|
+
chooses a decoder. A single resolve-then-route output that hides the codec
|
|
72
|
+
choice is [planned](../roadmap.md), not present.
|
|
73
|
+
|
|
74
|
+
## Related documentation
|
|
75
|
+
|
|
76
|
+
- [Resource lifecycle](resource-lifecycle.md) — how a resource is acquired,
|
|
77
|
+
prepared, and published.
|
|
78
|
+
- [Wwise formats](../formats/wwise.md) — the wem container these checks read.
|
|
79
|
+
- [Roadmap](../roadmap.md) — the unbuilt read-path integration.
|
package/docs/formats/README.md
CHANGED
|
@@ -72,6 +72,17 @@ Detailed pages: [Granny GR2 and GSF](gr2.md),
|
|
|
72
72
|
history, retained snapshots, and donor licensing are recorded in
|
|
73
73
|
[provenance.md](provenance.md).
|
|
74
74
|
|
|
75
|
+
`CjsPngFormat.inspect(bytes)` is the one-shot, decode-free PNG inspection
|
|
76
|
+
entry point. In addition to the header and bounded chunk summary, it exposes
|
|
77
|
+
the standard ancillary placement chunks when present:
|
|
78
|
+
|
|
79
|
+
- `offset: { x, y, unit }` from `oFFs`, with signed 32-bit coordinates; and
|
|
80
|
+
- `physicalPixelDimensions: { x, y, unit }` from `pHYs`, with unsigned 32-bit
|
|
81
|
+
values.
|
|
82
|
+
|
|
83
|
+
These are raw PNG facts. Runtime-resource does not assign character-atlas or
|
|
84
|
+
other domain semantics to their values.
|
|
85
|
+
|
|
75
86
|
## Black and Red reader boundary
|
|
76
87
|
|
|
77
88
|
`CjsBlackReader` and `CjsRedReader` share `CjsBlueReader` as an output and
|
package/docs/formats/wwise.md
CHANGED
|
@@ -140,6 +140,31 @@ media index-to-source mappings, RTPC curves, state values, and initial plug-in
|
|
|
140
140
|
property values. Opaque parameter bytes are intentional: a consumer must
|
|
141
141
|
qualify each plug-in's DSP behavior before interpreting them.
|
|
142
142
|
|
|
143
|
+
## Two facts about the pin and the container
|
|
144
|
+
|
|
145
|
+
**The version-150 pin has a horizon.** The typed decoding above is deliberately
|
|
146
|
+
bound to bank generator version 150, which is what current EVE builds ship. The
|
|
147
|
+
Wwise SDK that CarbonEngine itself pins is `2025.1.5.9095`, a generation whose
|
|
148
|
+
authoring tools emit a substantially later bank version. So the pin is expected
|
|
149
|
+
to be broken by a toolchain upgrade on the producing side rather than by
|
|
150
|
+
anything here, and the failure will look like whole-body rejection rather than
|
|
151
|
+
misreading: unknown or other-version bodies fall back to shallow action
|
|
152
|
+
type/target with `action: null`, which is the designed behavior. Treat a sudden
|
|
153
|
+
rise in `action: null` across a new build as a version bump, not corruption.
|
|
154
|
+
|
|
155
|
+
**EVE wems carry a chunk that is not part of Wwise's own layout.** Observed
|
|
156
|
+
between `fmt ` and `data`: a 24-byte `hash` chunk holding a 16-byte digest. The
|
|
157
|
+
engine never reads it, and its derivation is unverified — it is not the resource
|
|
158
|
+
index's whole-file md5. The repacker tolerates it structurally rather than by
|
|
159
|
+
name: the chunk walk records only `fmt `, `vorb`, `data`, and `smpl` and
|
|
160
|
+
advances past everything else, so an unrecognized chunk is skipped wherever it
|
|
161
|
+
appears. That is why the chunk is safe to ignore, and why it must stay safe —
|
|
162
|
+
a walk that assumed a fixed chunk order or a known-id whitelist would break on
|
|
163
|
+
these files.
|
|
164
|
+
|
|
165
|
+
Both observations are pinned to a 2026-07 corpus reading. Re-verify against a
|
|
166
|
+
current build before relying on either.
|
|
167
|
+
|
|
143
168
|
## Related documentation
|
|
144
169
|
|
|
145
170
|
- [Format subpaths](README.md)
|
package/docs/roadmap.md
CHANGED
|
@@ -130,6 +130,25 @@ playback or decoded-cache lifetime would unnecessarily retain both
|
|
|
130
130
|
representations. Runtime-lifetime and group retention remain caller policy
|
|
131
131
|
built from explicit tokens, not an implicit default on every loaded resource.
|
|
132
132
|
|
|
133
|
+
## Content-verified routing in the read path
|
|
134
|
+
|
|
135
|
+
[Type resolution](concepts/format-type-resolution.md) exists as a per-format
|
|
136
|
+
seam, but nothing in the resource read path consults it. `CjsResMan` still
|
|
137
|
+
picks a format by extension through the synchronous support check, so a
|
|
138
|
+
mislabeled container acquired the ordinary way is not corrected — only a caller
|
|
139
|
+
that invokes `resolveType()` directly gets the verified answer.
|
|
140
|
+
|
|
141
|
+
Wiring it in means awaiting a resolution between obtaining bytes and reading
|
|
142
|
+
them, letting the resolved route supply the default emit while a caller-forced
|
|
143
|
+
emit still wins, and deciding whether an extension tie-break may become
|
|
144
|
+
asynchronous. The cost question is the real one: the read path must not pay for
|
|
145
|
+
a content check on every resource merely because some format could opt in.
|
|
146
|
+
|
|
147
|
+
Alongside it, `CjsWemFormat` could expose a single resolve-then-route output so
|
|
148
|
+
a caller stops choosing between `raw`, `ogg`, and `pcm` for media whose codec
|
|
149
|
+
the reader has already established. Today all three are distinct declared
|
|
150
|
+
outputs.
|
|
151
|
+
|
|
133
152
|
## Open design questions
|
|
134
153
|
|
|
135
154
|
- Should `Unload()` drop only adapter payloads by default, or CPU payloads
|