@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
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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 // Carried so a consumer can answer \"may this sampler be overridden?\"\r\n // without inferring it. Carbon's compiler only makes a static sampler\r\n // out of a non-dynamic one -- `ConvertToStaticSampler` opens\r\n // `if( sampler.isDynamic ) { return false; }`\r\n // (shadercompiler/FXAnalyzer.cpp:1727-1731) -- so `false` is\r\n // guaranteed, not assumed, and there is no wire field to read.\r\n //\r\n // The flag is an authorisation, not decoration: dynamic means the\r\n // sampler may be overridden, non-dynamic means it must not be\r\n // touched. A reader that treats an absent flag as dynamic, which is\r\n // Carbon's default for the stage sampler that does carry one, would\r\n // offer an override on a sampler Carbon forbids overriding. Omitting\r\n // it therefore fails in the permissive direction.\r\n isDynamic: false,\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","isDynamic","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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"}
|
|
@@ -72,7 +72,9 @@ emitted bytes, so it need not preserve the original source alias partition. `mod
|
|
|
72
72
|
WGSL; it does not discard source permutations. `mode: "all"` attempts every
|
|
73
73
|
distinct body after the resolved selection passes the initial translation gate.
|
|
74
74
|
|
|
75
|
-
`.carbonwebgl`
|
|
75
|
+
`.carbonwebgl` is the **same** Carbon v15 record container as `.carbonwebgpu`,
|
|
76
|
+
carrying GLSL in the program slots and an optional per-pass backend block.
|
|
77
|
+
Neither has a private magic or chunk layout. Its package contract likewise
|
|
76
78
|
preserves complete source permutation topology and supports selected versus
|
|
77
79
|
all backend coverage.
|
|
78
80
|
|
|
@@ -90,6 +92,37 @@ one description record. No intermediate document sits between them.
|
|
|
90
92
|
What remains unproven is execution, not construction. The presence of every
|
|
91
93
|
permutation proves source preservation; it does not prove a rendered result.
|
|
92
94
|
|
|
95
|
+
## How an option list becomes a permutation index
|
|
96
|
+
|
|
97
|
+
`Tr2EffectRes.GetShader(options, count)` resolves a caller's option list to one
|
|
98
|
+
exact index. The rules are not obvious and each one has a consequence:
|
|
99
|
+
|
|
100
|
+
- **Mixed radix, first axis least significant.** The index accumulates as
|
|
101
|
+
`index += selectedIndex * multiplier`, with `multiplier` starting at 1 and
|
|
102
|
+
multiplying by each axis's option count in turn. An index is therefore only
|
|
103
|
+
meaningful against the axis order of that exact compiled effect.
|
|
104
|
+
- **A global option owns its axis outright.** If a global option matches the
|
|
105
|
+
axis name, the caller's local options for that axis are **not consulted at
|
|
106
|
+
all** — not even as a fallback.
|
|
107
|
+
- **An invalid global keeps the default and still blocks the local.** A global
|
|
108
|
+
naming a value the axis does not offer leaves the axis on `defaultOption`, and
|
|
109
|
+
the local option that *would* have been valid is still skipped. This is the
|
|
110
|
+
rule that surprises people: a typo in a global option silently pins an axis to
|
|
111
|
+
its default rather than erroring or deferring.
|
|
112
|
+
- **Among locals, the last valid one wins.** The scan does not stop at the first
|
|
113
|
+
match, so a later duplicate overrides an earlier one.
|
|
114
|
+
- **An unmatched or invalid value falls back to `defaultOption`**, never to
|
|
115
|
+
option 0 — the default is frequently not 0.
|
|
116
|
+
|
|
117
|
+
`GetShaderByIndex` **returns `null` for an index at or beyond the variant
|
|
118
|
+
count**. It does not clamp and it does not fall back to body 0. A caller that
|
|
119
|
+
treats `null` as "use the first body" reintroduces exactly the bug the null
|
|
120
|
+
exists to expose.
|
|
121
|
+
|
|
122
|
+
Selecting the default is rarely what a caller wants. A compiled axis can default
|
|
123
|
+
to one value while real construction selects another, so a caller qualifying a
|
|
124
|
+
shader should name the option explicitly and record the index it resolved to.
|
|
125
|
+
|
|
93
126
|
## Reading the model without inventing gaps
|
|
94
127
|
|
|
95
128
|
Three recurring mistakes explain most false conclusions in this area:
|
package/docs/formats/README.md
CHANGED
|
@@ -5,6 +5,22 @@ Scope: `@carbonenginejs/runtime-resource/formats`
|
|
|
5
5
|
Audience: Users and integrators
|
|
6
6
|
Summary: Maps every owned format subpath and records cross-format output conventions.
|
|
7
7
|
|
|
8
|
+
## Formats are decorator free
|
|
9
|
+
|
|
10
|
+
A format may not use a decorator, and may not import a module that does. This
|
|
11
|
+
is enforced by the package linter, not left to review.
|
|
12
|
+
|
|
13
|
+
A decorated module only parses after the build transform, so a format that
|
|
14
|
+
touches one stops being loadable from source. Every consumer reading `src/`
|
|
15
|
+
directly then fails with a bare syntax error pointing at the decorator rather
|
|
16
|
+
than at the import that reached it, which is a long way from the mistake.
|
|
17
|
+
|
|
18
|
+
The practical consequence is that a format reports a **plain probe-shaped
|
|
19
|
+
object** from `isSupported()` and `resolveType()` rather than constructing a
|
|
20
|
+
`CjsResourceProbe`, which is decorated. `CjsResourceProbe.from()` normalizes
|
|
21
|
+
those payloads wherever a real probe instance is wanted. See
|
|
22
|
+
[format type resolution](../concepts/format-type-resolution.md).
|
|
23
|
+
|
|
8
24
|
## Import rule
|
|
9
25
|
|
|
10
26
|
Concrete formats are never imported or registered by the package root. Each
|
|
@@ -58,6 +74,9 @@ metadata. Worker eligibility never changes the format's direct API; see
|
|
|
58
74
|
| Python pickle (`.pickle`, protocol 0 data subset) | `CjsPickleFormat` | `@carbonenginejs/runtime-resource/formats/pickle` |
|
|
59
75
|
| PNG (`.png`) | `CjsPngFormat` | `@carbonenginejs/runtime-resource/formats/png` |
|
|
60
76
|
| Red (`.red`) | `CjsRedFormat` | `@carbonenginejs/runtime-resource/formats/red` |
|
|
77
|
+
| Schema-bound containers (layout in a sibling schema) | `CjsSchemaBoundFormat` | `@carbonenginejs/runtime-resource/formats/schemabound` |
|
|
78
|
+
| SQLite 3 (`.sqlite`/`.db`) | `CjsSqliteFormat` | `@carbonenginejs/runtime-resource/formats/sqlite` |
|
|
79
|
+
| Client static data (`.static`, identification) | `CjsStaticFormat` | `@carbonenginejs/runtime-resource/formats/static` |
|
|
61
80
|
| STL (`.stl`) | `CjsStlFormat` | `@carbonenginejs/runtime-resource/formats/stl` |
|
|
62
81
|
| TGA (`.tga`) | `CjsTgaFormat` | `@carbonenginejs/runtime-resource/formats/tga` |
|
|
63
82
|
| WAV (`.wav`) | `CjsWavFormat` | `@carbonenginejs/runtime-resource/formats/wav` |
|
|
@@ -68,6 +87,8 @@ metadata. Worker eligibility never changes the format's direct API; see
|
|
|
68
87
|
|
|
69
88
|
Detailed pages: [Granny GR2 and GSF](gr2.md),
|
|
70
89
|
[data-only pickle protocol 0](pickle.md),
|
|
90
|
+
[client `.static` container identification](static.md),
|
|
91
|
+
[schema-bound containers](schemabound.md),
|
|
71
92
|
[Wwise soundbanks and media](wwise.md), and [STL export](stl.md). Ownership
|
|
72
93
|
history, retained snapshots, and donor licensing are recorded in
|
|
73
94
|
[provenance.md](provenance.md).
|
|
@@ -68,25 +68,40 @@ handles the rest. What emerges carries no version, so consumers above that
|
|
|
68
68
|
boundary are version-free. A port that preserves the same separation stays
|
|
69
69
|
consistent with Carbon.
|
|
70
70
|
|
|
71
|
-
### What this reader does:
|
|
72
|
-
|
|
73
|
-
`readEffectDescription` takes
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
### What this reader does: reads 8 through 15, writes 15
|
|
72
|
+
|
|
73
|
+
`readEffectDescription` takes the version as an option and branches on it, the
|
|
74
|
+
way Carbon's own reader always did. The accepted range is
|
|
75
|
+
`CARBON_EFFECT_MIN_DATA_VERSION` = 8 through `CARBON_EFFECT_DATA_VERSION` = 15;
|
|
76
|
+
anything outside it is rejected outright.
|
|
77
|
+
|
|
78
|
+
The reader was briefly constant-folded to 15, and the branches were restored on
|
|
79
|
+
2026-08-02.
|
|
80
|
+
|
|
81
|
+
Reading a version does not imply emitting it. The two ranges are independent and
|
|
82
|
+
deliberately so: reading a version needs a branch that interprets bytes, while
|
|
83
|
+
emitting one needs a branch that produces them.
|
|
84
|
+
|
|
85
|
+
**The emitted version is a parameter, not a constant.** `CjsCarbonEffectWriter`,
|
|
86
|
+
`writeCarbonEffectFile`, the shared container builder and both backend packagers
|
|
87
|
+
all take a `version` option, defaulting to the current version.
|
|
88
|
+
`CARBON_EFFECT_WRITE_VERSIONS` declares what the writer can actually produce —
|
|
89
|
+
today `[15]`, because the v15 shape is the only one we have writer branches for.
|
|
90
|
+
A version outside that set is **refused**, never emitted as v15 bytes under
|
|
91
|
+
another number, which would produce a file that lies about itself.
|
|
92
|
+
|
|
93
|
+
This is the shape that lets a future version land: add the branches, add the
|
|
94
|
+
entry, and every caller already passes the parameter. The source effect's
|
|
95
|
+
version never selects the emitted one — a package built from a v8 file is still
|
|
96
|
+
emitted at the version you asked for.
|
|
97
|
+
|
|
98
|
+
Rejecting outside the range is the correct failure mode rather than a limitation
|
|
99
|
+
to route around. Applying v15 rules to a version below 8 can misalign fields —
|
|
100
|
+
the comparisons above change which fields are present and how their bytes are
|
|
101
|
+
interpreted — and must not be attempted.
|
|
87
102
|
|
|
88
103
|
The reader rejects with the version it read, and does not classify it further.
|
|
89
|
-
A leading dword
|
|
104
|
+
A leading dword below 8 is a *recognized legacy version number*, not evidence
|
|
90
105
|
that the bytes are an effect container: arbitrary data can begin with a small
|
|
91
106
|
integer, and the version dword alone carries no magic or checksum to confirm it.
|
|
92
107
|
Anything that reaches this rejection needs identifying by other means before it
|
|
@@ -205,17 +220,28 @@ carries inline length-prefixed strings instead of references. A test pins the
|
|
|
205
220
|
property directly — the block's bytes must be identical whichever arena it is
|
|
206
221
|
interned into. Any future arena entry must satisfy the same rule.
|
|
207
222
|
|
|
208
|
-
###
|
|
223
|
+
### The non-dynamic sampler name is kept, though Carbon's runtime drops it
|
|
224
|
+
|
|
225
|
+
Carbon's *runtime* nulls a non-dynamic sampler's name while reading, precisely
|
|
226
|
+
because such a sampler is never looked up by name — `FindSamplerByName` only
|
|
227
|
+
matters for the dynamic case. **The file carries the string regardless, and this
|
|
228
|
+
reader keeps it**: `readSampler` and `writeSampler` handle `name` unconditionally,
|
|
229
|
+
whatever `isDynamic` says.
|
|
230
|
+
|
|
231
|
+
That is the rule, and it generalises: we re-emit the *file*, not Carbon's
|
|
232
|
+
in-memory view of it. Discarding what the runtime happens not to need is how a
|
|
233
|
+
byte-exact round trip stops being byte-exact. This field was one of **three**
|
|
234
|
+
such losses found together — the others being the authored stage order (21
|
|
235
|
+
files) and the offset word behind a zero-size blob (150 files) — and it was the
|
|
236
|
+
widest, affecting 1,631 files. All three are closed.
|
|
209
237
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
238
|
+
Each was invisible to a record-level comparison, because a record rebuilt from a
|
|
239
|
+
lossy class matches the lossy class it came from. Byte equality is the assertion
|
|
240
|
+
for that reason.
|
|
213
241
|
|
|
214
|
-
This
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
only matters for the dynamic case. Recorded here because it will otherwise be
|
|
218
|
-
rediscovered as a bug: a diff against the source effect will always show it.
|
|
242
|
+
This section previously said the opposite, describing the name as unrecoverable.
|
|
243
|
+
It was wrong, and it is the kind of wrong that gets rediscovered as a bug in the
|
|
244
|
+
other direction, so it is corrected here rather than deleted.
|
|
219
245
|
|
|
220
246
|
**Corollary: the container admits all six of Carbon's stage types.** `stages` is
|
|
221
247
|
capped at `SHADER_TYPE_COUNT` = 6, and the stage-type byte uses Carbon's
|
|
@@ -436,7 +462,8 @@ longer part of the package.
|
|
|
436
462
|
**Current WebGPU wire.** Carbon WebGPU bytes have no envelope, magic, `payloadKind`,
|
|
437
463
|
or independent container version. They are bare Carbon v15 records resolved
|
|
438
464
|
from `effect.webgpu/`, with one optional per-pass backend block. `.carbonwebgl`
|
|
439
|
-
|
|
465
|
+
is this same wire — the same records, the same reader, GLSL in the program slots
|
|
466
|
+
— and not a separate chunk format.
|
|
440
467
|
|
|
441
468
|
`CarbonWebgpuContainer` reads the optional blocks, and the shared record reader can
|
|
442
469
|
auto-detect them from a description's declared size. There is no adapter
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Schema-bound containers
|
|
2
|
+
|
|
3
|
+
Status: Experimental
|
|
4
|
+
Scope: `@carbonenginejs/runtime-resource/formats/schemabound`
|
|
5
|
+
Audience: Anyone reading client static data whose layout ships beside it
|
|
6
|
+
Summary: Reads a binary record container against the separate schema document that describes its layout, including the variable-length record section that makes a fixed-stride reader silently wrong.
|
|
7
|
+
|
|
8
|
+
## Why this exists
|
|
9
|
+
|
|
10
|
+
Some client containers carry no layout at all. They pair a binary payload with a
|
|
11
|
+
sibling schema document — YAML — that states every attribute's offset, width and
|
|
12
|
+
type, which fields are optional, how lists are strided, and how the container
|
|
13
|
+
indexes its own records.
|
|
14
|
+
|
|
15
|
+
That makes them the opposite of a hash-identified container, where the header
|
|
16
|
+
names a layout it does not describe and the layout has to be derived and pinned
|
|
17
|
+
per dataset. **Nothing needs deriving here.** Supply the schema and the payload
|
|
18
|
+
decodes.
|
|
19
|
+
|
|
20
|
+
It also makes them unusually easy to read wrongly. The bytes carry no signature,
|
|
21
|
+
no version and no field names, so given the wrong schema they decode into
|
|
22
|
+
plausible nonsense rather than failing — there is nothing in them to disagree
|
|
23
|
+
with. Pair each payload with the schema that shipped beside it.
|
|
24
|
+
|
|
25
|
+
## Use
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import { CjsSchemaBoundFormat } from
|
|
29
|
+
"@carbonenginejs/runtime-resource/formats/schemabound";
|
|
30
|
+
|
|
31
|
+
const records = CjsSchemaBoundFormat.read(payloadBytes, { schema: schemaBytes });
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`schema` accepts the schema document in any form it arrives in: YAML bytes, YAML
|
|
35
|
+
text, or an already-parsed object. YAML is parsed with `CjsYamlFormat`, and
|
|
36
|
+
anchors and aliases are rejoined — these schemas share repeated declarations that
|
|
37
|
+
way, and left unresolved an anchor reads as one more field.
|
|
38
|
+
|
|
39
|
+
- `read` / `readJSON` — plain JSON-compatible values; a wide integer becomes a
|
|
40
|
+
decimal string.
|
|
41
|
+
- `readPayload` — the same, with wide integers left as `BigInt`.
|
|
42
|
+
- `is` / `isSupported` — **these ask about the schema, not the payload.** These
|
|
43
|
+
containers have no signature, so claiming to recognize the bytes would be a
|
|
44
|
+
claim this format cannot support. Which family a `.static` file belongs to is
|
|
45
|
+
[`CjsStaticFormat`](static.md)'s question.
|
|
46
|
+
|
|
47
|
+
The root is whatever the schema declares: a keyed map decodes to an object, a
|
|
48
|
+
list decodes to an array.
|
|
49
|
+
|
|
50
|
+
## The format
|
|
51
|
+
|
|
52
|
+
Four properties are worth knowing before writing anything that consumes the
|
|
53
|
+
result. Each of them is a way to get a plausible wrong answer.
|
|
54
|
+
|
|
55
|
+
**A keyed container's index is at the end, and nothing points at it.** The last
|
|
56
|
+
four bytes of the block are the index's own size; the index starts that far back,
|
|
57
|
+
and begins with its entry count. Reading forward from the header will not find
|
|
58
|
+
it.
|
|
59
|
+
|
|
60
|
+
**Record offsets are relative to the four-byte length header, not to the file.**
|
|
61
|
+
Decoding from the file start reads one field early, and produces zeroes that look
|
|
62
|
+
like a wrong layout rather than a wrong base.
|
|
63
|
+
|
|
64
|
+
**The per-record offset table varies in length.** After the fixed attributes come
|
|
65
|
+
a presence bitfield and then one offset per attribute *actually present* — an
|
|
66
|
+
optional attribute whose bit is clear takes no slot. Consecutive records
|
|
67
|
+
therefore hold their variable data at different distances from their own start,
|
|
68
|
+
so a reader written around a constant stride decodes the first record correctly
|
|
69
|
+
and then drifts.
|
|
70
|
+
|
|
71
|
+
**A list has two framings and the schema says which.** `fixedItemSize` means the
|
|
72
|
+
items are packed at that stride. Its absence means they are variable, so the
|
|
73
|
+
count is followed by one offset per item, measured from the start of the list.
|
|
74
|
+
|
|
75
|
+
Two smaller rules:
|
|
76
|
+
|
|
77
|
+
- The presence bitfield is written whenever a record has a variable section at
|
|
78
|
+
all, including where nothing in it is optional and the field is always zero.
|
|
79
|
+
It is the offset table that shrinks, never the bitfield.
|
|
80
|
+
- An absent optional takes the default its schema declares. Where no default is
|
|
81
|
+
declared the attribute is left off the record entirely.
|
|
82
|
+
|
|
83
|
+
## Types
|
|
84
|
+
|
|
85
|
+
| Schema type | Decoded as |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `int` | number at the declared width; signed unless `min` is zero or more; `BigInt` beyond the safe range |
|
|
88
|
+
| `float` | number, single or double by declared size |
|
|
89
|
+
| `bool` | boolean |
|
|
90
|
+
| `enum` | the member's name, or its number when `readEnumValue` is set |
|
|
91
|
+
| `vector3` | an object keyed by the schema's own component aliases |
|
|
92
|
+
| `string`, `resPath` | length-prefixed UTF-8 |
|
|
93
|
+
| `list` | array, strided or offset-indexed as above |
|
|
94
|
+
| `dict` | object, framed exactly as the file's own root |
|
|
95
|
+
| `object` | record, as above |
|
|
96
|
+
|
|
97
|
+
## Evidence
|
|
98
|
+
|
|
99
|
+
The reader was verified field for field against the published static data export
|
|
100
|
+
for every container of this family in one build, and cross-checked between
|
|
101
|
+
containers that describe the same relationships from different sides. The
|
|
102
|
+
detailed measurements are recorded in the organization documentation rather than
|
|
103
|
+
here.
|
|
104
|
+
|
|
105
|
+
The tests in this package hold the structure instead, on containers laid out byte
|
|
106
|
+
by byte: the shrinking offset table, both list framings, declared defaults,
|
|
107
|
+
nested maps, anchors in the schema, and the widths ordinary data never reaches.
|
|
108
|
+
|
|
109
|
+
## Related documentation
|
|
110
|
+
|
|
111
|
+
- [Client `.static` container identification](static.md) — which family a file holds
|
|
112
|
+
- [Formats](README.md)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Client `.static` container identification
|
|
2
|
+
|
|
3
|
+
Status: Experimental
|
|
4
|
+
Scope: `@carbonenginejs/runtime-resource/formats/static`
|
|
5
|
+
Audience: Resource integrators reading client static data
|
|
6
|
+
Summary: Identifies which of three unrelated containers a `.static` file holds, so a caller can route it to the format that decodes it.
|
|
7
|
+
|
|
8
|
+
## Why this exists
|
|
9
|
+
|
|
10
|
+
`.static` names a role, not a format. Three unrelated containers ship under the
|
|
11
|
+
single extension, and each fails differently when guessed at. Measured across
|
|
12
|
+
the 45 `.static` files in one build:
|
|
13
|
+
|
|
14
|
+
| Family | Count | Signature |
|
|
15
|
+
|---|---:|---|
|
|
16
|
+
| SQLite 3 | 14 | `SQLite format 3\0` |
|
|
17
|
+
| Prefixed pickle | 25 | four-byte little-endian prefix, then `(d` or `(l` |
|
|
18
|
+
| Schema-bound | 6 | no signature; has a `.schema` companion |
|
|
19
|
+
|
|
20
|
+
The six unidentified files are exactly the six with a `.schema` companion —
|
|
21
|
+
`constellations`, `dialogs`, `factionsowningsolarsystems`, `jumps`, `regions`
|
|
22
|
+
and `systems` — so the detector's "unknown" set is not a gap in coverage but the
|
|
23
|
+
family that cannot be read without its companion.
|
|
24
|
+
|
|
25
|
+
## Boundary
|
|
26
|
+
|
|
27
|
+
`CjsStaticFormat` identifies. It decodes nothing.
|
|
28
|
+
|
|
29
|
+
- **SQLite** containers hold `cache(key, value, time)` and
|
|
30
|
+
`indexes(key, value)`, with a JSON document per record.
|
|
31
|
+
- **Prefixed pickle** containers are decoded through `CjsPickleFormat` after
|
|
32
|
+
the four-byte prefix.
|
|
33
|
+
- **Schema-bound** containers report `unknown` with `requires: "schema"`, and
|
|
34
|
+
are decoded by `CjsSchemaBoundFormat` once the caller has that companion.
|
|
35
|
+
|
|
36
|
+
Detection is signature-based. It never trusts a file name and never executes
|
|
37
|
+
anything.
|
|
38
|
+
|
|
39
|
+
## This format identifies; it does not decode
|
|
40
|
+
|
|
41
|
+
It reports the family, where the payload starts, and what is still missing. The
|
|
42
|
+
caller takes that to the format that owns the family:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const probe = await CjsStaticFormat.resolveType(bytes);
|
|
46
|
+
|
|
47
|
+
if (probe.preferred === CJS_STATIC_FAMILIES.SQLITE)
|
|
48
|
+
{
|
|
49
|
+
return CjsSqliteFormat.readJSON(bytes);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (probe.preferred === CJS_STATIC_FAMILIES.PICKLE)
|
|
53
|
+
{
|
|
54
|
+
return CjsPickleFormat.read(CjsStaticFormat.payload(bytes));
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**This changed on 2026-08-15.** A `read()` here dispatched to those two formats
|
|
59
|
+
itself, and the SQLite family additionally required a driver injected through
|
|
60
|
+
`options.sqlite`. Both are gone. An identification format should not be the
|
|
61
|
+
routing table for two others, and deciding what to decode belongs to whoever
|
|
62
|
+
asked. Nothing outside this format's own tests ever called `read()`.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## The pickles name classes, and the schemas describe layouts
|
|
66
|
+
|
|
67
|
+
Two notes that decide how the remaining families get decoded.
|
|
68
|
+
|
|
69
|
+
**The pickle family carries class-construction opcodes.** Protocol 0's `c`
|
|
70
|
+
(`GLOBAL`) names a module and an attribute for the unpickler to import, and
|
|
71
|
+
`R`/`i`/`o`/`b` then call it. That is the pickle remote-execution vector, so
|
|
72
|
+
`CjsPickleFormat` rejects those opcodes by design. Client `.static` pickles use
|
|
73
|
+
them legitimately, to name the classes their records are constructed from, so
|
|
74
|
+
decoding this family fully means mapping each named global to an inert
|
|
75
|
+
descriptor and never invoking it. **Not implemented**; the rejection is
|
|
76
|
+
surfaced rather than worked around, and widening it is a deliberate decision
|
|
77
|
+
rather than a bug fix.
|
|
78
|
+
|
|
79
|
+
**The schema-bound family is self-describing.** Its `.schema` companion is
|
|
80
|
+
YAML and states the whole binary layout — sizes, types, optional flags, list item
|
|
81
|
+
sizes, vector precision and a key-to-offset footer — so **nothing needs
|
|
82
|
+
deriving**, unlike an FSD container. `CjsSchemaBoundFormat` reads it:
|
|
83
|
+
[schema-bound containers](schemabound.md). All six datasets decode, the celestial
|
|
84
|
+
tables among them.
|
|
85
|
+
|
|
86
|
+
## Use
|
|
87
|
+
|
|
88
|
+
Identification goes through the shared type-resolution seam rather than a
|
|
89
|
+
private entry point — see [format type resolution](../concepts/format-type-resolution.md).
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { CjsStaticFormat, CJS_STATIC_FAMILIES } from
|
|
93
|
+
"@carbonenginejs/runtime-resource/formats/static";
|
|
94
|
+
|
|
95
|
+
const probe = await CjsStaticFormat.resolveType(bytes);
|
|
96
|
+
|
|
97
|
+
if (probe.preferred === CJS_STATIC_FAMILIES.PICKLE)
|
|
98
|
+
{
|
|
99
|
+
const value = CjsPickleFormat.read(CjsStaticFormat.payload(bytes));
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`isSupported()` and its `inspect()` alias report on the declaration seam;
|
|
104
|
+
`resolveType()` is the content-verified one. This format is an unusual case for
|
|
105
|
+
that contract: `.static` carries no in-band declaration at all, so there is
|
|
106
|
+
nothing for the content to disagree with. The signature is both claim and
|
|
107
|
+
evidence, `resolveType()` is therefore always `verified`, and `metadata.declared`
|
|
108
|
+
is `null` with `mismatch` always false.
|
|
109
|
+
|
|
110
|
+
`describe()` returns the underlying
|
|
111
|
+
`{ family, byteLength, payloadOffset, prefix, decodable, requires, reason }` without
|
|
112
|
+
building a probe. `payload()` returns the bytes past any wrapper, which is what a
|
|
113
|
+
caller hands to the format that owns the family.
|
|
114
|
+
|
|
115
|
+
## Related documentation
|
|
116
|
+
|
|
117
|
+
- [Formats](README.md)
|
|
118
|
+
- [Data-only pickle protocol 0](pickle.md)
|
|
119
|
+
- [Schema-bound containers](schemabound.md)
|
|
@@ -39,9 +39,11 @@ compiled effect bytes
|
|
|
39
39
|
The emitted artifact is a shared Carbon v15 container, not a tagged-chunk
|
|
40
40
|
package; the GLSL replaces the DXBC in each stage's program slot. Backend body
|
|
41
41
|
keys deliberately retain the historical `body_<offset>_<size>` form.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
The permutation graph still records every Cartesian permutation, its option
|
|
43
|
+
indices, its exact source record, and a content-deduplicated body identity — but
|
|
44
|
+
it is a **derived view** (`CJS_EFFECT_PERMUTATION_GRAPH`, built by
|
|
45
|
+
`buildEffectPermutationGraph`), not a stored `PGRF` chunk. That chunk and its
|
|
46
|
+
`EFFECT_PERMUTATION_GRAPH_CHUNK` export are retired; nothing emits or reads one.
|
|
45
47
|
|
|
46
48
|
## Completeness
|
|
47
49
|
|
|
@@ -16,8 +16,8 @@ Carbon version-15 records.
|
|
|
16
16
|
Unsupported requested shader semantics fail explicitly instead of producing a
|
|
17
17
|
partially translated selected pass. `BuildEffect` preserves every permutation
|
|
18
18
|
row and representable non-program description/reflection fields in the Carbon
|
|
19
|
-
container
|
|
20
|
-
|
|
19
|
+
container, including non-dynamic sampler names and the authored stage order.
|
|
20
|
+
Source-stage DXBC is replaced by WGSL or an empty program slot.
|
|
21
21
|
Selected mode writes WGSL only for the resolved body's requested passes; all
|
|
22
22
|
mode attempts every distinct body after the resolved body passes the initial
|
|
23
23
|
translation gate. Backend and runtime completeness remain broader gates.
|