@carbonenginejs/runtime-resource 0.10.0 → 0.11.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/effect/effectPermutationGraph.js +257 -0
- package/dist/format/effect/effectPermutationGraph.js.map +1 -0
- package/dist/format/effect/effectReflectionPackage.js +636 -0
- package/dist/format/effect/effectReflectionPackage.js.map +1 -0
- package/dist/format/effect/sha256.js +114 -0
- package/dist/format/effect/sha256.js.map +1 -0
- package/dist/formats/dxbc/CjsDxbcFormat.js +142 -0
- package/dist/formats/dxbc/CjsDxbcFormat.js.map +1 -0
- package/dist/formats/dxbc/core/DxbcReader.js +266 -0
- package/dist/formats/dxbc/core/DxbcReader.js.map +1 -0
- package/dist/formats/dxbc/core/container.js +169 -0
- package/dist/formats/dxbc/core/container.js.map +1 -0
- package/dist/formats/dxbc/core/decoder.js +789 -0
- package/dist/formats/dxbc/core/decoder.js.map +1 -0
- package/dist/formats/dxbc/core/errors.js +19 -0
- package/dist/formats/dxbc/core/errors.js.map +1 -0
- package/dist/formats/dxbc/core/helpers.js +220 -0
- package/dist/formats/dxbc/core/helpers.js.map +1 -0
- package/dist/formats/dxbc/core/opcodes.js +45 -0
- package/dist/formats/dxbc/core/opcodes.js.map +1 -0
- package/dist/formats/dxbc/core/program.js +91 -0
- package/dist/formats/dxbc/core/program.js.map +1 -0
- package/dist/formats/dxbc/core/signature.js +172 -0
- package/dist/formats/dxbc/core/signature.js.map +1 -0
- package/dist/formats/dxbc/index.js +2 -0
- package/dist/formats/dxbc/index.js.map +1 -0
- package/dist/formats/hlsl/CjsHlslFormat.js +254 -0
- package/dist/formats/hlsl/CjsHlslFormat.js.map +1 -0
- package/dist/formats/hlsl/core/HlslBinaryUtils.js +15 -0
- package/dist/formats/hlsl/core/HlslBinaryUtils.js.map +1 -0
- package/dist/formats/hlsl/core/HlslEffectReadError.js +19 -0
- package/dist/formats/hlsl/core/HlslEffectReadError.js.map +1 -0
- package/dist/formats/hlsl/core/HlslEffectStateManager.js +130 -0
- package/dist/formats/hlsl/core/HlslEffectStateManager.js.map +1 -0
- package/dist/formats/hlsl/core/HlslReader.js +266 -0
- package/dist/formats/hlsl/core/HlslReader.js.map +1 -0
- package/dist/formats/hlsl/core/HlslRenderStateSetup.js +37 -0
- package/dist/formats/hlsl/core/HlslRenderStateSetup.js.map +1 -0
- package/dist/formats/hlsl/core/HlslResourceSetDescription.js +94 -0
- package/dist/formats/hlsl/core/HlslResourceSetDescription.js.map +1 -0
- package/dist/formats/hlsl/core/HlslShaderBytecode.js +44 -0
- package/dist/formats/hlsl/core/HlslShaderBytecode.js.map +1 -0
- package/dist/formats/hlsl/core/analysis.js +51 -0
- package/dist/formats/hlsl/core/analysis.js.map +1 -0
- package/dist/formats/hlsl/core/helpers.js +270 -0
- package/dist/formats/hlsl/core/helpers.js.map +1 -0
- package/dist/formats/hlsl/core/json.js +284 -0
- package/dist/formats/hlsl/core/json.js.map +1 -0
- package/dist/formats/hlsl/core/metadata.js +327 -0
- package/dist/formats/hlsl/core/metadata.js.map +1 -0
- package/dist/formats/hlsl/core/portableReflection.js +848 -0
- package/dist/formats/hlsl/core/portableReflection.js.map +1 -0
- package/dist/formats/hlsl/core/render-states.js +280 -0
- package/dist/formats/hlsl/core/render-states.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js +43 -0
- package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +294 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js +33 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +416 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js +40 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js +742 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js +52 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js +38 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js +50 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js +86 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js +31 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslPass.js +42 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslPass.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js +55 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js +29 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShader.js +220 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShader.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js +30 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js.map +1 -0
- package/dist/formats/hlsl/index.js +2 -0
- package/dist/formats/hlsl/index.js.map +1 -0
- package/dist/formats/hlsl/portable.js +2 -0
- package/dist/formats/hlsl/portable.js.map +1 -0
- package/dist/formats/index.js +4 -0
- package/dist/formats/index.js.map +1 -1
- package/dist/formats/webgl/CjsWebglFormat.js +221 -0
- package/dist/formats/webgl/CjsWebglFormat.js.map +1 -0
- package/dist/formats/webgl/core/cewg/CewgPackage.js +339 -0
- package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -0
- package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js +104 -0
- package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js.map +1 -0
- package/dist/formats/webgl/core/cewg/binary.js +101 -0
- package/dist/formats/webgl/core/cewg/binary.js.map +1 -0
- package/dist/formats/webgl/core/cewgCompleteness.js +81 -0
- package/dist/formats/webgl/core/cewgCompleteness.js.map +1 -0
- package/dist/formats/webgl/core/effectPackage.js +789 -0
- package/dist/formats/webgl/core/effectPackage.js.map +1 -0
- package/dist/formats/webgl/core/effectPackageValidation.js +331 -0
- package/dist/formats/webgl/core/effectPackageValidation.js.map +1 -0
- package/dist/formats/webgl/core/errors.js +27 -0
- package/dist/formats/webgl/core/errors.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +2678 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js +89 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js +428 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js.map +1 -0
- package/dist/formats/webgl/core/helpers.js +306 -0
- package/dist/formats/webgl/core/helpers.js.map +1 -0
- package/dist/formats/webgl/index.js +2 -0
- package/dist/formats/webgl/index.js.map +1 -0
- package/dist/formats/webgpu/CjsWebgpuFormat.js +376 -0
- package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +415 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +100 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/binary.js +93 -0
- package/dist/formats/webgpu/core/cewgpu/binary.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/tags.js +17 -0
- package/dist/formats/webgpu/core/cewgpu/tags.js.map +1 -0
- package/dist/formats/webgpu/core/effectAnalysis.js +82 -0
- package/dist/formats/webgpu/core/effectAnalysis.js.map +1 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js +305 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -0
- package/dist/formats/webgpu/core/effectPackageValidation.js +1078 -0
- package/dist/formats/webgpu/core/effectPackageValidation.js.map +1 -0
- package/dist/formats/webgpu/core/errors.js +20 -0
- package/dist/formats/webgpu/core/errors.js.map +1 -0
- package/dist/formats/webgpu/core/helpers.js +448 -0
- package/dist/formats/webgpu/core/helpers.js.map +1 -0
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +223 -0
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -0
- package/dist/formats/webgpu/core/ir/buildControlFlow.js +220 -0
- package/dist/formats/webgpu/core/ir/buildControlFlow.js.map +1 -0
- package/dist/formats/webgpu/core/ir/indexableTemps.js +137 -0
- package/dist/formats/webgpu/core/ir/indexableTemps.js.map +1 -0
- package/dist/formats/webgpu/core/ir/inferValueTypes.js +454 -0
- package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -0
- package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js +494 -0
- package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js.map +1 -0
- package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js +177 -0
- package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js.map +1 -0
- package/dist/formats/webgpu/core/ir/sourceLanes.js +61 -0
- package/dist/formats/webgpu/core/ir/sourceLanes.js.map +1 -0
- package/dist/formats/webgpu/core/packageEffect.js +300 -0
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -0
- package/dist/formats/webgpu/core/packageEffectSelection.js +164 -0
- package/dist/formats/webgpu/core/packageEffectSelection.js.map +1 -0
- package/dist/formats/webgpu/core/packageMetadata.js +8 -0
- package/dist/formats/webgpu/core/packageMetadata.js.map +1 -0
- package/dist/formats/webgpu/core/schema.js +4 -0
- package/dist/formats/webgpu/core/schema.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +275 -0
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +182 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +324 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/emitWgsl.js +356 -0
- package/dist/formats/webgpu/core/wgsl/emitWgsl.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js +77 -0
- package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js +451 -0
- package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +754 -0
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js +457 -0
- package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js +1572 -0
- package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js +659 -0
- package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js +734 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js +583 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js +621 -0
- package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js +824 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js +697 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js +559 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js +1328 -0
- package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js +110 -0
- package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/precisionControls.js +55 -0
- package/dist/formats/webgpu/core/wgsl/precisionControls.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js +758 -0
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/uniformity.js +78 -0
- package/dist/formats/webgpu/core/wgsl/uniformity.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js +196 -0
- package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js +37 -0
- package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js.map +1 -0
- package/dist/formats/webgpu/index.js +2 -0
- package/dist/formats/webgpu/index.js.map +1 -0
- package/dist/resource/shader/Tr2EffectRes.js +159 -150
- package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialArea.js +23 -28
- package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialMesh.js +21 -27
- package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialRes.js +24 -29
- package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
- package/dist/resource/shader/Tr2Shader.js +45 -39
- package/dist/resource/shader/Tr2Shader.js.map +1 -1
- package/dist/resource/shader/Tr2ShaderPermutation.js +30 -32
- package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectConstant.js +113 -78
- package/dist/resource/shader/reflection/Tr2EffectConstant.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDefine.js +17 -23
- package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDescription.js +23 -29
- package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js +44 -40
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +82 -86
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +55 -61
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +49 -45
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js +25 -30
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +30 -32
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js +21 -26
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
- package/docs/formats/README.md +4 -0
- package/docs/formats/provenance.md +11 -3
- package/docs/reference/classes/formats.md +440 -0
- package/format-notices/dxbc/LICENSE +21 -0
- package/format-notices/dxbc/NOTICE +20 -0
- package/format-notices/hlsl/LICENSE +21 -0
- package/format-notices/hlsl/NOTICE +25 -0
- package/format-notices/webgl/LICENSE +21 -0
- package/format-notices/webgl/NOTICE +35 -0
- package/format-notices/webgpu/LICENSE +21 -0
- package/format-notices/webgpu/NOTICE +31 -0
- package/package.json +6 -1
- package/dist/resource/shader/portableValidation.js +0 -461
- package/dist/resource/shader/portableValidation.js.map +0 -1
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
import { enumerateUniqueEffectBodies, buildEffectBodyReflection, EFFECT_BODY_REFLECTION_VERSION, EFFECT_BODY_REFLECTION_FORMAT, validateEffectBodyReflection } from '../../formats/hlsl/core/portableReflection.js';
|
|
2
|
+
import { sha256Bytes, sha256Utf8 } from './sha256.js';
|
|
3
|
+
|
|
4
|
+
const EFFECT_REFLECTION_CHUNK = "RFLX";
|
|
5
|
+
const EFFECT_REFLECTION_BLOB_CHUNK = "RBLB";
|
|
6
|
+
const EFFECT_REFLECTION_FORMAT = "CJS_EFFECT_REFLECTION";
|
|
7
|
+
const EFFECT_REFLECTION_VERSION = 2;
|
|
8
|
+
const SHA256 = /^[0-9a-f]{64}$/u;
|
|
9
|
+
const SELECTED_EFFECT_REFLECTION_VERSION = 1;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build complete unique-body source reflection plus one deduplicated byte
|
|
13
|
+
* arena while retaining body-local portable keys.
|
|
14
|
+
*
|
|
15
|
+
* @param {object} effectRes Loaded format-hlsl Tr2EffectRes.
|
|
16
|
+
* @param {object} permutationGraph Complete source PGRF document.
|
|
17
|
+
* @param {object} options Source identity and diagnostic label.
|
|
18
|
+
* @param {object} options.sourceIdentity Canonical INFO source identity.
|
|
19
|
+
* @param {string} options.sourcePath Diagnostic INFO/META/ANLS source label.
|
|
20
|
+
* @returns {{reflection:object,blobBytes:Uint8Array,pointer:object,counts:object}}
|
|
21
|
+
* Frozen all-unique reflection documents and owned blob bytes.
|
|
22
|
+
*/
|
|
23
|
+
function buildCompleteEffectReflection(effectRes, permutationGraph, options) {
|
|
24
|
+
const sourceBytes = effectRes?.m_data;
|
|
25
|
+
if (!(sourceBytes instanceof Uint8Array) || options?.sourceIdentity?.byteLength !== sourceBytes.byteLength || options?.sourceIdentity?.sha256 !== sha256Bytes(sourceBytes)) {
|
|
26
|
+
throw new Error("Complete effect reflection source identity disagrees with exact source bytes");
|
|
27
|
+
}
|
|
28
|
+
const inventory = enumerateUniqueEffectBodies(effectRes);
|
|
29
|
+
if (inventory.length !== permutationGraph?.bodies?.length) {
|
|
30
|
+
throw new Error("Complete effect reflection body inventory disagrees with PGRF");
|
|
31
|
+
}
|
|
32
|
+
const store = new ReflectionBlobStore();
|
|
33
|
+
let source = null;
|
|
34
|
+
const bodies = inventory.map((group, bodyIndex) => {
|
|
35
|
+
const graphBody = permutationGraph.bodies[bodyIndex];
|
|
36
|
+
const representative = selectedVariant(permutationGraph, group.permutationIndex);
|
|
37
|
+
if (representative.bodyKey !== graphBody?.key || group.variants.some(variant => {
|
|
38
|
+
const graphVariant = selectedVariant(permutationGraph, variant.permutationIndex);
|
|
39
|
+
return graphVariant.bodyKey !== graphBody.key || graphVariant.sourceRecord.offset !== variant.sourceRecord.offset || graphVariant.sourceRecord.byteLength !== variant.sourceRecord.byteLength;
|
|
40
|
+
})) {
|
|
41
|
+
throw new Error(`Complete effect reflection body ${bodyIndex} aliases disagree with PGRF`);
|
|
42
|
+
}
|
|
43
|
+
const portable = buildEffectBodyReflection(effectRes, group.permutationIndex);
|
|
44
|
+
if (portable.sourceRecord.offset !== group.sourceRecord.offset || portable.sourceRecord.byteLength !== group.sourceRecord.byteLength) {
|
|
45
|
+
throw new Error(`Complete effect reflection body ${bodyIndex} source record changed`);
|
|
46
|
+
}
|
|
47
|
+
if (!source) {
|
|
48
|
+
source = {
|
|
49
|
+
label: portable.source.label,
|
|
50
|
+
effectVersion: portable.source.effectVersion,
|
|
51
|
+
compilerVersion: portable.source.compilerVersion,
|
|
52
|
+
nativeHash: store.add(portable.source.nativeHash),
|
|
53
|
+
stringTableByteLength: portable.source.stringTableByteLength,
|
|
54
|
+
byteLength: portable.source.byteLength,
|
|
55
|
+
sha256: options.sourceIdentity.sha256
|
|
56
|
+
};
|
|
57
|
+
} else if (!samePortableSource(source, portable.source, store)) {
|
|
58
|
+
throw new Error(`Complete effect reflection body ${bodyIndex} source envelope changed`);
|
|
59
|
+
}
|
|
60
|
+
const exactBodyBytes = sourceBytes.subarray(portable.sourceRecord.offset, portable.sourceRecord.offset + portable.sourceRecord.byteLength);
|
|
61
|
+
if (graphBody.byteLength !== exactBodyBytes.byteLength || graphBody.sha256 !== sha256Bytes(exactBodyBytes)) {
|
|
62
|
+
throw new Error(`Complete effect reflection body ${bodyIndex} identity disagrees with PGRF`);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
bodyKey: graphBody.key,
|
|
66
|
+
representativePermutationIndex: group.permutationIndex,
|
|
67
|
+
byteLength: graphBody.byteLength,
|
|
68
|
+
sha256: graphBody.sha256,
|
|
69
|
+
effect: packByteArrays(portable.effect, store)
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
const blobBytes = store.finish();
|
|
73
|
+
const reflection = {
|
|
74
|
+
format: EFFECT_REFLECTION_FORMAT,
|
|
75
|
+
formatVersion: EFFECT_REFLECTION_VERSION,
|
|
76
|
+
portableFormat: EFFECT_BODY_REFLECTION_FORMAT,
|
|
77
|
+
portableFormatVersion: EFFECT_BODY_REFLECTION_VERSION,
|
|
78
|
+
keyScope: "body-local",
|
|
79
|
+
coverage: {
|
|
80
|
+
bodies: "all-unique",
|
|
81
|
+
reflection: "complete-for-listed",
|
|
82
|
+
sourcePrograms: "complete-for-listed",
|
|
83
|
+
constantDefaults: "exact-for-listed"
|
|
84
|
+
},
|
|
85
|
+
source,
|
|
86
|
+
bodies,
|
|
87
|
+
blobStore: {
|
|
88
|
+
chunk: EFFECT_REFLECTION_BLOB_CHUNK,
|
|
89
|
+
byteLength: blobBytes.byteLength,
|
|
90
|
+
sha256: sha256Bytes(blobBytes),
|
|
91
|
+
blobCount: store.entries.length,
|
|
92
|
+
blobs: store.entries.map(entry => ({
|
|
93
|
+
...entry
|
|
94
|
+
}))
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const counts = validateCompleteEffectReflection(reflection, blobBytes, {
|
|
98
|
+
permutationGraph,
|
|
99
|
+
sourceIdentity: options.sourceIdentity,
|
|
100
|
+
sourcePath: options.sourcePath
|
|
101
|
+
});
|
|
102
|
+
const pointer = {
|
|
103
|
+
chunk: EFFECT_REFLECTION_CHUNK,
|
|
104
|
+
format: EFFECT_REFLECTION_FORMAT,
|
|
105
|
+
formatVersion: EFFECT_REFLECTION_VERSION,
|
|
106
|
+
blobChunk: EFFECT_REFLECTION_BLOB_CHUNK,
|
|
107
|
+
sha256: sha256Utf8(`${JSON.stringify(reflection)}\n`),
|
|
108
|
+
coverage: "all-unique",
|
|
109
|
+
permutationCount: permutationGraph.variants.length,
|
|
110
|
+
bodyCount: counts.bodyCount,
|
|
111
|
+
sourceProgramCount: counts.sourceProgramCount,
|
|
112
|
+
blobCount: counts.blobCount,
|
|
113
|
+
blobByteLength: counts.blobByteLength
|
|
114
|
+
};
|
|
115
|
+
return Object.freeze({
|
|
116
|
+
reflection: deepFreeze(reflection),
|
|
117
|
+
blobBytes,
|
|
118
|
+
pointer: Object.freeze(pointer),
|
|
119
|
+
counts
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Validate selected-body reflection against its binary store, PGRF, and INFO
|
|
125
|
+
* source identity.
|
|
126
|
+
*
|
|
127
|
+
* @param {object} reflection Parsed RFLX document.
|
|
128
|
+
* @param {Uint8Array} blobBytes Raw RBLB chunk bytes.
|
|
129
|
+
* @param {object} options Reconciliation context.
|
|
130
|
+
* @param {object} options.permutationGraph Validated complete PGRF document.
|
|
131
|
+
* @param {number} options.permutationIndex Package-selected permutation index.
|
|
132
|
+
* @param {object} options.sourceIdentity Validated INFO source identity.
|
|
133
|
+
* @param {string} options.sourcePath Validated INFO source label.
|
|
134
|
+
* @returns {{bodyCount:number,sourceProgramCount:number,blobCount:number,blobByteLength:number}}
|
|
135
|
+
* Validated selected reflection counts.
|
|
136
|
+
*/
|
|
137
|
+
function validateSelectedEffectReflection(reflection, blobBytes, options) {
|
|
138
|
+
requireExactKeys(reflection, ["format", "formatVersion", "portableFormat", "portableFormatVersion", "keyScope", "coverage", "selectedBody", "source", "effect", "blobStore"], "CEWGPU RFLX");
|
|
139
|
+
requireExactKeys(reflection.coverage, ["bodies", "reflection", "sourcePrograms", "constantDefaults"], "CEWGPU RFLX.coverage");
|
|
140
|
+
if (reflection.format !== EFFECT_REFLECTION_FORMAT || reflection.formatVersion !== SELECTED_EFFECT_REFLECTION_VERSION || reflection.portableFormat !== EFFECT_BODY_REFLECTION_FORMAT || reflection.portableFormatVersion !== EFFECT_BODY_REFLECTION_VERSION || reflection.keyScope !== "body-local" || reflection.coverage.bodies !== "selected" || reflection.coverage.reflection !== "complete-for-listed" || reflection.coverage.sourcePrograms !== "complete-for-listed" || reflection.coverage.constantDefaults !== "exact-for-listed") {
|
|
141
|
+
throw new Error("CEWGPU RFLX schema or coverage is unsupported");
|
|
142
|
+
}
|
|
143
|
+
const graph = requireRecord(options?.permutationGraph, "CEWGPU RFLX permutation graph");
|
|
144
|
+
const sourceIdentity = requireRecord(options?.sourceIdentity, "CEWGPU RFLX source identity");
|
|
145
|
+
const sourcePath = requireString(options?.sourcePath, "CEWGPU RFLX sourcePath");
|
|
146
|
+
const selected = requireRecord(reflection.selectedBody, "CEWGPU RFLX.selectedBody");
|
|
147
|
+
requireExactKeys(selected, ["permutationIndex", "bodyKey", "sourceRecord", "byteLength", "sha256"], "CEWGPU RFLX.selectedBody");
|
|
148
|
+
requireUint(selected.permutationIndex, "CEWGPU RFLX selected permutationIndex");
|
|
149
|
+
if (selected.permutationIndex !== options?.permutationIndex) {
|
|
150
|
+
throw new Error("CEWGPU RFLX selected body disagrees with META");
|
|
151
|
+
}
|
|
152
|
+
requireString(selected.bodyKey, "CEWGPU RFLX selected bodyKey");
|
|
153
|
+
requireUint(selected.byteLength, "CEWGPU RFLX selected byteLength", true);
|
|
154
|
+
requireSha256(selected.sha256, "CEWGPU RFLX selected sha256");
|
|
155
|
+
const sourceRecord = requireRecord(selected.sourceRecord, "CEWGPU RFLX selected sourceRecord");
|
|
156
|
+
requireExactKeys(sourceRecord, ["offset", "byteLength"], "CEWGPU RFLX selected sourceRecord");
|
|
157
|
+
requireUint(sourceRecord.offset, "CEWGPU RFLX selected sourceRecord offset");
|
|
158
|
+
requireUint(sourceRecord.byteLength, "CEWGPU RFLX selected sourceRecord byteLength", true);
|
|
159
|
+
const variant = selectedVariant(graph, selected.permutationIndex);
|
|
160
|
+
const body = selectedBody(graph, selected.bodyKey);
|
|
161
|
+
if (variant.bodyKey !== selected.bodyKey || variant.sourceRecord.offset !== sourceRecord.offset || variant.sourceRecord.byteLength !== sourceRecord.byteLength || selected.byteLength !== body.byteLength || sourceRecord.byteLength !== body.byteLength || selected.sha256 !== body.sha256) {
|
|
162
|
+
throw new Error("CEWGPU RFLX selected body disagrees with PGRF");
|
|
163
|
+
}
|
|
164
|
+
const source = requireRecord(reflection.source, "CEWGPU RFLX.source");
|
|
165
|
+
requireExactKeys(source, ["label", "effectVersion", "compilerVersion", "nativeHash", "stringTableByteLength", "byteLength", "sha256"], "CEWGPU RFLX.source");
|
|
166
|
+
if (source.label !== sourcePath || source.byteLength !== sourceIdentity.byteLength || source.sha256 !== sourceIdentity.sha256) {
|
|
167
|
+
throw new Error("CEWGPU RFLX source identity disagrees with INFO");
|
|
168
|
+
}
|
|
169
|
+
requireSha256(source.sha256, "CEWGPU RFLX source sha256");
|
|
170
|
+
const blobInventory = validateBlobStore(reflection.blobStore, blobBytes);
|
|
171
|
+
const usedBlobKeys = new Set();
|
|
172
|
+
const portable = {
|
|
173
|
+
format: reflection.portableFormat,
|
|
174
|
+
formatVersion: reflection.portableFormatVersion,
|
|
175
|
+
mode: "single-body",
|
|
176
|
+
keyScope: reflection.keyScope,
|
|
177
|
+
coverage: {
|
|
178
|
+
bodies: "single",
|
|
179
|
+
reflection: "complete",
|
|
180
|
+
sourcePrograms: "complete",
|
|
181
|
+
constantDefaults: "exact"
|
|
182
|
+
},
|
|
183
|
+
source: {
|
|
184
|
+
label: source.label,
|
|
185
|
+
effectVersion: source.effectVersion,
|
|
186
|
+
compilerVersion: source.compilerVersion,
|
|
187
|
+
nativeHash: unpackBlobReference(source.nativeHash, blobInventory, blobBytes, usedBlobKeys),
|
|
188
|
+
stringTableByteLength: source.stringTableByteLength,
|
|
189
|
+
byteLength: source.byteLength
|
|
190
|
+
},
|
|
191
|
+
permutationIndex: selected.permutationIndex,
|
|
192
|
+
sourceRecord: {
|
|
193
|
+
offset: sourceRecord.offset,
|
|
194
|
+
byteLength: sourceRecord.byteLength
|
|
195
|
+
},
|
|
196
|
+
effect: unpackByteReferences(reflection.effect, blobInventory, blobBytes, usedBlobKeys)
|
|
197
|
+
};
|
|
198
|
+
const portableCounts = validateEffectBodyReflection(portable);
|
|
199
|
+
if (usedBlobKeys.size !== blobInventory.size) {
|
|
200
|
+
throw new Error("CEWGPU RFLX blob store contains unreferenced payloads");
|
|
201
|
+
}
|
|
202
|
+
return Object.freeze({
|
|
203
|
+
bodyCount: 1,
|
|
204
|
+
sourceProgramCount: portableCounts.sourceProgramCount,
|
|
205
|
+
blobCount: blobInventory.size,
|
|
206
|
+
blobByteLength: blobBytes.byteLength
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Validate complete unique-body reflection against PGRF and its shared byte
|
|
212
|
+
* arena.
|
|
213
|
+
*
|
|
214
|
+
* @param {object} reflection Parsed RFLX v2 document.
|
|
215
|
+
* @param {Uint8Array} blobBytes Raw RBLB bytes.
|
|
216
|
+
* @param {object} options Reconciliation context.
|
|
217
|
+
* @param {object} options.permutationGraph Validated complete PGRF document.
|
|
218
|
+
* @param {object} options.sourceIdentity Validated INFO source identity.
|
|
219
|
+
* @param {string} options.sourcePath Validated INFO source label.
|
|
220
|
+
* @returns {{permutationCount:number,bodyCount:number,sourceProgramCount:number,blobCount:number,blobByteLength:number}}
|
|
221
|
+
* Validated complete source-reflection counts.
|
|
222
|
+
*/
|
|
223
|
+
function validateCompleteEffectReflection(reflection, blobBytes, options) {
|
|
224
|
+
requireExactKeys(reflection, ["format", "formatVersion", "portableFormat", "portableFormatVersion", "keyScope", "coverage", "source", "bodies", "blobStore"], "CEWGPU RFLX");
|
|
225
|
+
requireExactKeys(reflection.coverage, ["bodies", "reflection", "sourcePrograms", "constantDefaults"], "CEWGPU RFLX.coverage");
|
|
226
|
+
if (reflection.format !== EFFECT_REFLECTION_FORMAT || reflection.formatVersion !== EFFECT_REFLECTION_VERSION || reflection.portableFormat !== EFFECT_BODY_REFLECTION_FORMAT || reflection.portableFormatVersion !== EFFECT_BODY_REFLECTION_VERSION || reflection.keyScope !== "body-local" || reflection.coverage.bodies !== "all-unique" || reflection.coverage.reflection !== "complete-for-listed" || reflection.coverage.sourcePrograms !== "complete-for-listed" || reflection.coverage.constantDefaults !== "exact-for-listed" || !Array.isArray(reflection.bodies)) {
|
|
227
|
+
throw new Error("CEWGPU RFLX schema or coverage is unsupported");
|
|
228
|
+
}
|
|
229
|
+
const graph = requireRecord(options?.permutationGraph, "CEWGPU RFLX permutation graph");
|
|
230
|
+
const sourceIdentity = requireRecord(options?.sourceIdentity, "CEWGPU RFLX source identity");
|
|
231
|
+
const sourcePath = requireString(options?.sourcePath, "CEWGPU RFLX sourcePath");
|
|
232
|
+
if (reflection.bodies.length !== graph.bodies?.length) {
|
|
233
|
+
throw new Error("CEWGPU RFLX does not cover every PGRF body");
|
|
234
|
+
}
|
|
235
|
+
const source = requireRecord(reflection.source, "CEWGPU RFLX.source");
|
|
236
|
+
requireExactKeys(source, ["label", "effectVersion", "compilerVersion", "nativeHash", "stringTableByteLength", "byteLength", "sha256"], "CEWGPU RFLX.source");
|
|
237
|
+
if (source.label !== sourcePath || source.byteLength !== sourceIdentity.byteLength || source.sha256 !== sourceIdentity.sha256) {
|
|
238
|
+
throw new Error("CEWGPU RFLX source identity disagrees with INFO");
|
|
239
|
+
}
|
|
240
|
+
requireSha256(source.sha256, "CEWGPU RFLX source sha256");
|
|
241
|
+
const blobInventory = validateBlobStore(reflection.blobStore, blobBytes);
|
|
242
|
+
const usedBlobKeys = new Set();
|
|
243
|
+
const nativeHash = unpackBlobReference(source.nativeHash, blobInventory, blobBytes, usedBlobKeys);
|
|
244
|
+
const representativeByBodyKey = new Map();
|
|
245
|
+
for (const variant of graph.variants) {
|
|
246
|
+
if (!representativeByBodyKey.has(variant.bodyKey)) {
|
|
247
|
+
representativeByBodyKey.set(variant.bodyKey, variant);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
let sourceProgramCount = 0;
|
|
251
|
+
for (const [bodyIndex, reflectedBody] of reflection.bodies.entries()) {
|
|
252
|
+
requireExactKeys(reflectedBody, ["bodyKey", "representativePermutationIndex", "byteLength", "sha256", "effect"], `CEWGPU RFLX body ${bodyIndex}`);
|
|
253
|
+
const graphBody = graph.bodies[bodyIndex];
|
|
254
|
+
requireString(reflectedBody.bodyKey, `CEWGPU RFLX body ${bodyIndex} key`);
|
|
255
|
+
requireUint(reflectedBody.representativePermutationIndex, `CEWGPU RFLX body ${bodyIndex} representative`);
|
|
256
|
+
requireUint(reflectedBody.byteLength, `CEWGPU RFLX body ${bodyIndex} byteLength`, true);
|
|
257
|
+
requireSha256(reflectedBody.sha256, `CEWGPU RFLX body ${bodyIndex} sha256`);
|
|
258
|
+
const representative = representativeByBodyKey.get(reflectedBody.bodyKey);
|
|
259
|
+
if (!graphBody || reflectedBody.bodyKey !== graphBody.key || reflectedBody.byteLength !== graphBody.byteLength || reflectedBody.sha256 !== graphBody.sha256 || !representative || reflectedBody.representativePermutationIndex !== representative.permutationIndex) {
|
|
260
|
+
throw new Error(`CEWGPU RFLX body ${bodyIndex} disagrees with PGRF`);
|
|
261
|
+
}
|
|
262
|
+
const portable = {
|
|
263
|
+
format: reflection.portableFormat,
|
|
264
|
+
formatVersion: reflection.portableFormatVersion,
|
|
265
|
+
mode: "single-body",
|
|
266
|
+
keyScope: reflection.keyScope,
|
|
267
|
+
coverage: {
|
|
268
|
+
bodies: "single",
|
|
269
|
+
reflection: "complete",
|
|
270
|
+
sourcePrograms: "complete",
|
|
271
|
+
constantDefaults: "exact"
|
|
272
|
+
},
|
|
273
|
+
source: {
|
|
274
|
+
label: source.label,
|
|
275
|
+
effectVersion: source.effectVersion,
|
|
276
|
+
compilerVersion: source.compilerVersion,
|
|
277
|
+
nativeHash: Uint8Array.from(nativeHash),
|
|
278
|
+
stringTableByteLength: source.stringTableByteLength,
|
|
279
|
+
byteLength: source.byteLength
|
|
280
|
+
},
|
|
281
|
+
permutationIndex: representative.permutationIndex,
|
|
282
|
+
sourceRecord: {
|
|
283
|
+
...representative.sourceRecord
|
|
284
|
+
},
|
|
285
|
+
effect: unpackByteReferences(reflectedBody.effect, blobInventory, blobBytes, usedBlobKeys)
|
|
286
|
+
};
|
|
287
|
+
sourceProgramCount += validateEffectBodyReflection(portable).sourceProgramCount;
|
|
288
|
+
}
|
|
289
|
+
if (usedBlobKeys.size !== blobInventory.size) {
|
|
290
|
+
throw new Error("CEWGPU RFLX blob store contains unreferenced payloads");
|
|
291
|
+
}
|
|
292
|
+
return Object.freeze({
|
|
293
|
+
permutationCount: graph.variants.length,
|
|
294
|
+
bodyCount: reflection.bodies.length,
|
|
295
|
+
sourceProgramCount,
|
|
296
|
+
blobCount: blobInventory.size,
|
|
297
|
+
blobByteLength: blobBytes.byteLength
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Validate an INFO reflection pointer against parsed RFLX/RBLB payloads.
|
|
303
|
+
*
|
|
304
|
+
* @param {object} pointer INFO reflection pointer.
|
|
305
|
+
* @param {object} reflection Parsed RFLX document.
|
|
306
|
+
* @param {Uint8Array} blobBytes Raw RBLB bytes.
|
|
307
|
+
* @param {object} options Reconciliation context for RFLX.
|
|
308
|
+
* @param {Uint8Array} [options.reflectionBytes] Exact RFLX chunk bytes for v2.
|
|
309
|
+
* @returns {object} Validated reflection counts.
|
|
310
|
+
*/
|
|
311
|
+
function validateEffectReflectionPointer(pointer, reflection, blobBytes, options) {
|
|
312
|
+
const version = pointer?.formatVersion;
|
|
313
|
+
requireExactKeys(pointer, version === EFFECT_REFLECTION_VERSION ? ["chunk", "format", "formatVersion", "blobChunk", "sha256", "coverage", "permutationCount", "bodyCount", "sourceProgramCount", "blobCount", "blobByteLength"] : ["chunk", "format", "formatVersion", "blobChunk", "bodyCount", "sourceProgramCount", "blobCount", "blobByteLength"], "CEWGPU INFO.effectReflection");
|
|
314
|
+
if (pointer.chunk !== EFFECT_REFLECTION_CHUNK || pointer.format !== EFFECT_REFLECTION_FORMAT || ![SELECTED_EFFECT_REFLECTION_VERSION, EFFECT_REFLECTION_VERSION].includes(version) || pointer.blobChunk !== EFFECT_REFLECTION_BLOB_CHUNK) {
|
|
315
|
+
throw new Error("CEWGPU INFO.effectReflection is malformed");
|
|
316
|
+
}
|
|
317
|
+
for (const field of ["bodyCount", "sourceProgramCount", "blobCount", "blobByteLength"]) {
|
|
318
|
+
requireUint(pointer[field], `CEWGPU INFO.effectReflection.${field}`);
|
|
319
|
+
}
|
|
320
|
+
let counts;
|
|
321
|
+
if (version === EFFECT_REFLECTION_VERSION) {
|
|
322
|
+
requireSha256(pointer.sha256, "CEWGPU INFO.effectReflection.sha256");
|
|
323
|
+
if (!(options?.reflectionBytes instanceof Uint8Array) || sha256Bytes(options.reflectionBytes) !== pointer.sha256) {
|
|
324
|
+
throw new Error("CEWGPU INFO effect-reflection digest disagrees with RFLX");
|
|
325
|
+
}
|
|
326
|
+
if (pointer.coverage !== "all-unique") {
|
|
327
|
+
throw new Error("CEWGPU INFO.effectReflection is malformed");
|
|
328
|
+
}
|
|
329
|
+
requireUint(pointer.permutationCount, "CEWGPU INFO.effectReflection.permutationCount", true);
|
|
330
|
+
counts = validateCompleteEffectReflection(reflection, blobBytes, options);
|
|
331
|
+
if (pointer.permutationCount !== counts.permutationCount) {
|
|
332
|
+
throw new Error("CEWGPU INFO effect-reflection counts disagree with RFLX/RBLB");
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
counts = validateSelectedEffectReflection(reflection, blobBytes, options);
|
|
336
|
+
}
|
|
337
|
+
if (pointer.bodyCount !== counts.bodyCount || pointer.sourceProgramCount !== counts.sourceProgramCount || pointer.blobCount !== counts.blobCount || pointer.blobByteLength !== counts.blobByteLength) {
|
|
338
|
+
throw new Error("CEWGPU INFO effect-reflection counts disagree with RFLX/RBLB");
|
|
339
|
+
}
|
|
340
|
+
return counts;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Selects the body-local reflected effect for one PGRF permutation.
|
|
345
|
+
*
|
|
346
|
+
* @param {object} reflection Validated RFLX v1 or v2 document.
|
|
347
|
+
* @param {object} permutationGraph Validated PGRF document.
|
|
348
|
+
* @param {number} permutationIndex Exact package-selected permutation index.
|
|
349
|
+
* @returns {object} Reflected body-local effect graph.
|
|
350
|
+
*/
|
|
351
|
+
function effectReflectionForPermutation(reflection, permutationGraph, permutationIndex) {
|
|
352
|
+
const variant = selectedVariant(permutationGraph, permutationIndex);
|
|
353
|
+
if (reflection?.formatVersion === SELECTED_EFFECT_REFLECTION_VERSION) {
|
|
354
|
+
if (reflection.selectedBody?.permutationIndex !== permutationIndex || reflection.selectedBody?.bodyKey !== variant.bodyKey) {
|
|
355
|
+
throw new Error("CEWGPU selected RFLX body disagrees with PGRF");
|
|
356
|
+
}
|
|
357
|
+
return requireRecord(reflection.effect, "CEWGPU RFLX.effect");
|
|
358
|
+
}
|
|
359
|
+
if (reflection?.formatVersion === EFFECT_REFLECTION_VERSION) {
|
|
360
|
+
const body = reflection.bodies?.find(entry => entry.bodyKey === variant.bodyKey);
|
|
361
|
+
return requireRecord(body?.effect, "CEWGPU RFLX selected effect");
|
|
362
|
+
}
|
|
363
|
+
throw new Error("CEWGPU RFLX schema or coverage is unsupported");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Hydrates one package permutation into the validated portable reflection
|
|
368
|
+
* contract owned by format-hlsl.
|
|
369
|
+
*
|
|
370
|
+
* @param {object} reflection Validated RFLX v1 or v2 document.
|
|
371
|
+
* @param {object} permutationGraph Validated PGRF document.
|
|
372
|
+
* @param {number} permutationIndex Exact package permutation index.
|
|
373
|
+
* @param {(reference:object)=>Uint8Array|null} resolveBlob Exact RBLB resolver.
|
|
374
|
+
* @returns {object} Fresh portable single-body reflection with owned bytes.
|
|
375
|
+
*/
|
|
376
|
+
function hydrateEffectReflectionForPermutation(reflection, permutationGraph, permutationIndex, resolveBlob) {
|
|
377
|
+
if (typeof resolveBlob !== "function") {
|
|
378
|
+
throw new TypeError("CEWGPU reflection blob resolver must be a function");
|
|
379
|
+
}
|
|
380
|
+
const variant = selectedVariant(permutationGraph, permutationIndex);
|
|
381
|
+
const selected = reflection?.formatVersion === SELECTED_EFFECT_REFLECTION_VERSION ? reflection.selectedBody : variant;
|
|
382
|
+
const cache = new Map();
|
|
383
|
+
const portable = {
|
|
384
|
+
format: reflection?.portableFormat,
|
|
385
|
+
formatVersion: reflection?.portableFormatVersion,
|
|
386
|
+
mode: "single-body",
|
|
387
|
+
keyScope: reflection?.keyScope,
|
|
388
|
+
coverage: {
|
|
389
|
+
bodies: "single",
|
|
390
|
+
reflection: "complete",
|
|
391
|
+
sourcePrograms: "complete",
|
|
392
|
+
constantDefaults: "exact"
|
|
393
|
+
},
|
|
394
|
+
source: {
|
|
395
|
+
label: reflection?.source?.label,
|
|
396
|
+
effectVersion: reflection?.source?.effectVersion,
|
|
397
|
+
compilerVersion: reflection?.source?.compilerVersion,
|
|
398
|
+
nativeHash: hydrateResolvedBytes(reflection?.source?.nativeHash, resolveBlob, cache),
|
|
399
|
+
stringTableByteLength: reflection?.source?.stringTableByteLength,
|
|
400
|
+
byteLength: reflection?.source?.byteLength
|
|
401
|
+
},
|
|
402
|
+
permutationIndex,
|
|
403
|
+
sourceRecord: {
|
|
404
|
+
...selected?.sourceRecord
|
|
405
|
+
},
|
|
406
|
+
effect: hydrateResolvedBytes(effectReflectionForPermutation(reflection, permutationGraph, permutationIndex), resolveBlob, cache)
|
|
407
|
+
};
|
|
408
|
+
validateEffectBodyReflection(portable);
|
|
409
|
+
return portable;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Builds a deterministic deduplicated byte arena for portable reflection.
|
|
414
|
+
*/
|
|
415
|
+
class ReflectionBlobStore {
|
|
416
|
+
/**
|
|
417
|
+
* Initializes an empty first-seen blob inventory.
|
|
418
|
+
*/
|
|
419
|
+
constructor() {
|
|
420
|
+
this.payloads = [];
|
|
421
|
+
this.entries = [];
|
|
422
|
+
this.byDigest = new Map();
|
|
423
|
+
this.byteLength = 0;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Adds exact bytes and returns their canonical immutable reference.
|
|
428
|
+
*
|
|
429
|
+
* @param {Uint8Array} value Portable reflection bytes.
|
|
430
|
+
* @returns {object} Canonical blob reference.
|
|
431
|
+
*/
|
|
432
|
+
add(value) {
|
|
433
|
+
if (!(value instanceof Uint8Array)) {
|
|
434
|
+
throw new TypeError("Selected effect reflection bytes must be Uint8Array");
|
|
435
|
+
}
|
|
436
|
+
const bytes = Uint8Array.from(value);
|
|
437
|
+
const sha256 = sha256Bytes(bytes);
|
|
438
|
+
const candidates = this.byDigest.get(sha256) ?? [];
|
|
439
|
+
const existing = candidates.find(candidate => bytesEqual(candidate.bytes, bytes));
|
|
440
|
+
if (existing) {
|
|
441
|
+
return Object.freeze({
|
|
442
|
+
...existing.reference
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
if (candidates.length) {
|
|
446
|
+
throw new Error("Selected effect reflection SHA-256 collision detected");
|
|
447
|
+
}
|
|
448
|
+
const entry = Object.freeze({
|
|
449
|
+
blobKey: `blob${this.entries.length}`,
|
|
450
|
+
offset: this.byteLength,
|
|
451
|
+
byteLength: bytes.byteLength,
|
|
452
|
+
sha256
|
|
453
|
+
});
|
|
454
|
+
const record = {
|
|
455
|
+
bytes,
|
|
456
|
+
reference: entry
|
|
457
|
+
};
|
|
458
|
+
candidates.push(record);
|
|
459
|
+
this.byDigest.set(sha256, candidates);
|
|
460
|
+
this.payloads.push(bytes);
|
|
461
|
+
this.entries.push(entry);
|
|
462
|
+
this.byteLength += bytes.byteLength;
|
|
463
|
+
return Object.freeze({
|
|
464
|
+
...entry
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Materializes the contiguous blob arena in inventory order.
|
|
470
|
+
*
|
|
471
|
+
* @returns {Uint8Array} Owned RBLB payload.
|
|
472
|
+
*/
|
|
473
|
+
finish() {
|
|
474
|
+
const out = new Uint8Array(this.byteLength);
|
|
475
|
+
let offset = 0;
|
|
476
|
+
for (const bytes of this.payloads) {
|
|
477
|
+
out.set(bytes, offset);
|
|
478
|
+
offset += bytes.byteLength;
|
|
479
|
+
}
|
|
480
|
+
return out;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function samePortableSource(source, portableSource, store) {
|
|
484
|
+
const nativeHash = store.add(portableSource.nativeHash);
|
|
485
|
+
return source.label === portableSource.label && source.effectVersion === portableSource.effectVersion && source.compilerVersion === portableSource.compilerVersion && source.stringTableByteLength === portableSource.stringTableByteLength && source.byteLength === portableSource.byteLength && source.nativeHash.blobKey === nativeHash.blobKey && source.nativeHash.offset === nativeHash.offset && source.nativeHash.byteLength === nativeHash.byteLength && source.nativeHash.sha256 === nativeHash.sha256;
|
|
486
|
+
}
|
|
487
|
+
function packByteArrays(value, store) {
|
|
488
|
+
if (value instanceof Uint8Array) return store.add(value);
|
|
489
|
+
if (Array.isArray(value)) {
|
|
490
|
+
return value.map(entry => packByteArrays(entry, store));
|
|
491
|
+
}
|
|
492
|
+
if (isRecord(value)) {
|
|
493
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, packByteArrays(entry, store)]));
|
|
494
|
+
}
|
|
495
|
+
return value;
|
|
496
|
+
}
|
|
497
|
+
function unpackByteReferences(value, inventory, blobBytes, usedBlobKeys) {
|
|
498
|
+
if (isBlobReference(value)) {
|
|
499
|
+
return unpackBlobReference(value, inventory, blobBytes, usedBlobKeys);
|
|
500
|
+
}
|
|
501
|
+
if (Array.isArray(value)) {
|
|
502
|
+
return value.map(entry => unpackByteReferences(entry, inventory, blobBytes, usedBlobKeys));
|
|
503
|
+
}
|
|
504
|
+
if (isRecord(value)) {
|
|
505
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, unpackByteReferences(entry, inventory, blobBytes, usedBlobKeys)]));
|
|
506
|
+
}
|
|
507
|
+
return value;
|
|
508
|
+
}
|
|
509
|
+
function unpackBlobReference(reference, inventory, blobBytes, usedBlobKeys) {
|
|
510
|
+
requireExactKeys(reference, ["blobKey", "offset", "byteLength", "sha256"], "CEWGPU RFLX blob reference");
|
|
511
|
+
const entry = inventory.get(reference.blobKey);
|
|
512
|
+
if (!entry || reference.offset !== entry.offset || reference.byteLength !== entry.byteLength || reference.sha256 !== entry.sha256) {
|
|
513
|
+
throw new Error("CEWGPU RFLX blob reference disagrees with its inventory");
|
|
514
|
+
}
|
|
515
|
+
usedBlobKeys.add(reference.blobKey);
|
|
516
|
+
return Uint8Array.from(blobBytes.subarray(reference.offset, reference.offset + reference.byteLength));
|
|
517
|
+
}
|
|
518
|
+
function validateBlobStore(blobStore, blobBytes) {
|
|
519
|
+
requireExactKeys(blobStore, ["chunk", "byteLength", "sha256", "blobCount", "blobs"], "CEWGPU RFLX.blobStore");
|
|
520
|
+
if (!(blobBytes instanceof Uint8Array)) {
|
|
521
|
+
throw new Error("CEWGPU RBLB must be raw Uint8Array bytes");
|
|
522
|
+
}
|
|
523
|
+
if (blobStore.chunk !== EFFECT_REFLECTION_BLOB_CHUNK || blobStore.byteLength !== blobBytes.byteLength || blobStore.sha256 !== sha256Bytes(blobBytes) || !Array.isArray(blobStore.blobs) || blobStore.blobCount !== blobStore.blobs.length) {
|
|
524
|
+
throw new Error("CEWGPU RFLX blob-store envelope disagrees with RBLB");
|
|
525
|
+
}
|
|
526
|
+
requireSha256(blobStore.sha256, "CEWGPU RFLX blob-store sha256");
|
|
527
|
+
const inventory = new Map();
|
|
528
|
+
const digests = new Set();
|
|
529
|
+
let expectedOffset = 0;
|
|
530
|
+
for (const [index, entry] of blobStore.blobs.entries()) {
|
|
531
|
+
requireExactKeys(entry, ["blobKey", "offset", "byteLength", "sha256"], `CEWGPU RFLX blob ${index}`);
|
|
532
|
+
if (entry.blobKey !== `blob${index}`) {
|
|
533
|
+
throw new Error(`CEWGPU RFLX blob ${index} has a noncanonical key`);
|
|
534
|
+
}
|
|
535
|
+
requireUint(entry.offset, `CEWGPU RFLX blob ${index} offset`);
|
|
536
|
+
requireUint(entry.byteLength, `CEWGPU RFLX blob ${index} byteLength`);
|
|
537
|
+
requireSha256(entry.sha256, `CEWGPU RFLX blob ${index} sha256`);
|
|
538
|
+
const end = entry.offset + entry.byteLength;
|
|
539
|
+
if (entry.offset !== expectedOffset || end > blobBytes.byteLength || digests.has(entry.sha256) || sha256Bytes(blobBytes.subarray(entry.offset, end)) !== entry.sha256) {
|
|
540
|
+
throw new Error(`CEWGPU RFLX blob ${index} is malformed or duplicated`);
|
|
541
|
+
}
|
|
542
|
+
inventory.set(entry.blobKey, entry);
|
|
543
|
+
digests.add(entry.sha256);
|
|
544
|
+
expectedOffset = end;
|
|
545
|
+
}
|
|
546
|
+
if (expectedOffset !== blobBytes.byteLength) {
|
|
547
|
+
throw new Error("CEWGPU RFLX blob inventory does not cover RBLB");
|
|
548
|
+
}
|
|
549
|
+
return inventory;
|
|
550
|
+
}
|
|
551
|
+
function selectedVariant(graph, permutationIndex) {
|
|
552
|
+
const variant = graph?.variants?.[permutationIndex];
|
|
553
|
+
if (!variant || variant.permutationIndex !== permutationIndex) {
|
|
554
|
+
throw new Error(`Selected effect reflection body ${permutationIndex} is absent from PGRF`);
|
|
555
|
+
}
|
|
556
|
+
return variant;
|
|
557
|
+
}
|
|
558
|
+
function selectedBody(graph, bodyKey) {
|
|
559
|
+
const body = graph?.bodies?.find(entry => entry.key === bodyKey);
|
|
560
|
+
if (!body) {
|
|
561
|
+
throw new Error(`Selected effect reflection body ${bodyKey} is absent from PGRF`);
|
|
562
|
+
}
|
|
563
|
+
return body;
|
|
564
|
+
}
|
|
565
|
+
function isBlobReference(value) {
|
|
566
|
+
return isRecord(value) && Object.prototype.hasOwnProperty.call(value, "blobKey") && Object.prototype.hasOwnProperty.call(value, "offset") && Object.prototype.hasOwnProperty.call(value, "byteLength") && Object.prototype.hasOwnProperty.call(value, "sha256");
|
|
567
|
+
}
|
|
568
|
+
function hydrateResolvedBytes(value, resolveBlob, cache) {
|
|
569
|
+
if (isBlobReference(value)) {
|
|
570
|
+
const key = [value.blobKey, value.offset, value.byteLength, value.sha256].join(":");
|
|
571
|
+
if (!cache.has(key)) {
|
|
572
|
+
const bytes = resolveBlob(value);
|
|
573
|
+
if (!(bytes instanceof Uint8Array)) {
|
|
574
|
+
throw new Error(`CEWGPU reflection blob ${value.blobKey} is unavailable`);
|
|
575
|
+
}
|
|
576
|
+
cache.set(key, bytes);
|
|
577
|
+
}
|
|
578
|
+
return Uint8Array.from(cache.get(key));
|
|
579
|
+
}
|
|
580
|
+
if (Array.isArray(value)) {
|
|
581
|
+
return value.map(entry => hydrateResolvedBytes(entry, resolveBlob, cache));
|
|
582
|
+
}
|
|
583
|
+
if (isRecord(value)) {
|
|
584
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, hydrateResolvedBytes(entry, resolveBlob, cache)]));
|
|
585
|
+
}
|
|
586
|
+
return value;
|
|
587
|
+
}
|
|
588
|
+
function requireExactKeys(value, allowed, context) {
|
|
589
|
+
requireRecord(value, context);
|
|
590
|
+
const keys = Reflect.ownKeys(value);
|
|
591
|
+
if (keys.length !== allowed.length || keys.some(key => typeof key !== "string" || !allowed.includes(key))) {
|
|
592
|
+
throw new Error(`${context} has unsupported or missing fields`);
|
|
593
|
+
}
|
|
594
|
+
return value;
|
|
595
|
+
}
|
|
596
|
+
function requireRecord(value, context) {
|
|
597
|
+
if (!isRecord(value)) {
|
|
598
|
+
throw new Error(`${context} must be an object`);
|
|
599
|
+
}
|
|
600
|
+
return value;
|
|
601
|
+
}
|
|
602
|
+
function requireString(value, context) {
|
|
603
|
+
if (typeof value !== "string" || !value || value !== value.trim()) {
|
|
604
|
+
throw new Error(`${context} must be a non-empty string`);
|
|
605
|
+
}
|
|
606
|
+
return value;
|
|
607
|
+
}
|
|
608
|
+
function requireSha256(value, context) {
|
|
609
|
+
if (typeof value !== "string" || !SHA256.test(value)) {
|
|
610
|
+
throw new Error(`${context} must be lowercase SHA-256`);
|
|
611
|
+
}
|
|
612
|
+
return value;
|
|
613
|
+
}
|
|
614
|
+
function requireUint(value, context, positive = false) {
|
|
615
|
+
if (!Number.isSafeInteger(value) || value < (positive ? 1 : 0) || value > 0xffffffff) {
|
|
616
|
+
throw new Error(`${context} must fit uint32`);
|
|
617
|
+
}
|
|
618
|
+
return value;
|
|
619
|
+
}
|
|
620
|
+
function isRecord(value) {
|
|
621
|
+
return !!value && typeof value === "object" && !Array.isArray(value) && !ArrayBuffer.isView(value);
|
|
622
|
+
}
|
|
623
|
+
function bytesEqual(left, right) {
|
|
624
|
+
return left.byteLength === right.byteLength && left.every((value, index) => value === right[index]);
|
|
625
|
+
}
|
|
626
|
+
function deepFreeze(value) {
|
|
627
|
+
if (!value || typeof value !== "object" || Object.isFrozen(value) || ArrayBuffer.isView(value)) {
|
|
628
|
+
return value;
|
|
629
|
+
}
|
|
630
|
+
Object.freeze(value);
|
|
631
|
+
for (const entry of Object.values(value)) deepFreeze(entry);
|
|
632
|
+
return value;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export { EFFECT_REFLECTION_BLOB_CHUNK, EFFECT_REFLECTION_CHUNK, EFFECT_REFLECTION_FORMAT, EFFECT_REFLECTION_VERSION, buildCompleteEffectReflection, effectReflectionForPermutation, hydrateEffectReflectionForPermutation, validateCompleteEffectReflection, validateEffectReflectionPointer, validateSelectedEffectReflection };
|
|
636
|
+
//# sourceMappingURL=effectReflectionPackage.js.map
|