@carbonenginejs/runtime-resource 0.12.0 → 0.12.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/CjsResMan.js +4 -4
- package/dist/CjsResMan.js.map +1 -1
- package/dist/_virtual/_rollupPluginBabelHelpers.js +1 -4
- package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
- package/dist/format/CjsByteReader.js +310 -0
- package/dist/format/CjsByteReader.js.map +1 -0
- package/dist/format/CjsByteWriter.js +242 -0
- package/dist/format/CjsByteWriter.js.map +1 -0
- package/dist/format/CjsFormatError.js +41 -0
- package/dist/format/CjsFormatError.js.map +1 -0
- package/dist/format/CjsStringTable.js +268 -0
- package/dist/format/CjsStringTable.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js +361 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js +373 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js +372 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js +427 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js +955 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js.map +1 -0
- package/dist/format/compareUtf8.js +36 -0
- package/dist/format/compareUtf8.js.map +1 -0
- package/dist/format/index.js +11 -0
- package/dist/format/index.js.map +1 -0
- package/dist/formats/bnk/CjsBnkFormat.js +10 -4
- package/dist/formats/bnk/CjsBnkFormat.js.map +1 -1
- package/dist/formats/bnk/core/eventAction.js +305 -0
- package/dist/formats/bnk/core/eventAction.js.map +1 -0
- package/dist/formats/bnk/core/helpers.js +11 -2
- package/dist/formats/bnk/core/helpers.js.map +1 -1
- package/dist/formats/bnk/core/nodeBase.js +532 -0
- package/dist/formats/bnk/core/nodeBase.js.map +1 -0
- package/dist/formats/bnk/core/sfxNodes.js +252 -152
- package/dist/formats/bnk/core/sfxNodes.js.map +1 -1
- package/dist/formats/hlsl/core/HlslReader.js +7 -257
- package/dist/formats/hlsl/core/HlslReader.js.map +1 -1
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js +781 -0
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +21 -1
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -1
- package/dist/formats/index.js +1 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js +2 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -1
- package/dist/formats/webgl/core/cewg/binary.js +11 -93
- package/dist/formats/webgl/core/cewg/binary.js.map +1 -1
- package/dist/formats/webgl/core/effectPackage.js +1 -1
- package/dist/formats/webgpu/CjsWebgpuFormat.js +4 -23
- package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -1
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js +197 -0
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js +368 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js +355 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js +90 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js.map +1 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js +21 -20
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -1
- package/dist/formats/webgpu/core/helpers.js +87 -92
- package/dist/formats/webgpu/core/helpers.js.map +1 -1
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +14 -13
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -1
- package/dist/formats/webgpu/core/ir/inferValueTypes.js +10 -8
- package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -1
- package/dist/formats/webgpu/core/packageEffect.js +94 -9
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -1
- package/dist/formats/webgpu/core/packageMetadata.js +10 -1
- package/dist/formats/webgpu/core/packageMetadata.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +17 -15
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +13 -12
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +9 -8
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +23 -22
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js +46 -44
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -1
- package/dist/resource/CjsResource.js +700 -684
- package/dist/resource/CjsResource.js.map +1 -1
- package/dist/resource/Tr2LightProfileRes.js +18 -27
- package/dist/resource/Tr2LightProfileRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioBufferRes.js +2 -2
- package/dist/resource/audio/CjsAudioBufferRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioRes.js +2 -2
- package/dist/resource/audio/CjsAudioRes.js.map +1 -1
- package/dist/resource/geometry/TriGeometryRes.js +605 -586
- package/dist/resource/geometry/TriGeometryRes.js.map +1 -1
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js +21 -30
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js.map +1 -1
- package/dist/resource/geometry/granny/TriGrannyRes.js +21 -30
- package/dist/resource/geometry/granny/TriGrannyRes.js.map +1 -1
- package/dist/resource/shader/Tr2EffectRes.js +9 -7
- package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialArea.js +5 -3
- package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialMesh.js +4 -2
- package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialRes.js +5 -3
- package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
- package/dist/resource/shader/Tr2Shader.js +26 -21
- package/dist/resource/shader/Tr2Shader.js.map +1 -1
- package/dist/resource/shader/Tr2ShaderPermutation.js +8 -6
- package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDefine.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDescription.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js +17 -15
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +11 -9
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +8 -6
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +15 -13
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js +7 -5
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +11 -9
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js +8 -6
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
- package/dist/resource/texture/CjsTextureArrayRes.js +400 -411
- package/dist/resource/texture/CjsTextureArrayRes.js.map +1 -1
- package/dist/resource/texture/Tr2ImageRes.js +99 -95
- package/dist/resource/texture/Tr2ImageRes.js.map +1 -1
- package/dist/resource/texture/TriTextureRes.js +312 -273
- package/dist/resource/texture/TriTextureRes.js.map +1 -1
- package/docs/README.md +13 -1
- package/docs/architecture.md +3 -3
- package/docs/concepts/resource-lifecycle.md +9 -2
- package/docs/concepts/shader-resource-model.md +114 -0
- package/docs/concepts/writing-an-engine-adapter.md +115 -0
- package/docs/formats/README.md +24 -1
- package/docs/formats/carbon-effect-container.md +452 -0
- package/docs/formats/dxbc/reference/classes/README.md +5 -72
- package/docs/formats/hlsl/reference/api.md +5 -4
- package/docs/formats/hlsl/reference/classes/README.md +6 -11
- package/docs/formats/provenance.md +23 -13
- package/docs/formats/webgl/reference/classes/README.md +5 -92
- package/docs/formats/webgpu/README.md +19 -16
- package/docs/formats/webgpu/architecture.md +15 -12
- package/docs/formats/webgpu/formats/cewgpu.md +175 -438
- package/docs/formats/webgpu/guides/effect-packaging.md +132 -140
- package/docs/formats/webgpu/reference/api.md +131 -131
- package/docs/formats/webgpu/reference/classes/README.md +5 -62
- package/docs/formats/webgpu/reference/wgsl-compatibility.md +146 -45
- package/docs/formats/wwise.md +34 -8
- package/docs/reference/classes/core.md +80 -0
- package/docs/reference/classes/formats.md +18 -28
- package/docs/reference/events.md +25 -0
- package/docs/reference/motherlode-cache.md +22 -8
- package/docs/reference/workers.md +5 -5
- package/docs/roadmap.md +61 -41
- package/package.json +2 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +0 -415
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +0 -100
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/binary.js +0 -93
- package/dist/formats/webgpu/core/cewgpu/binary.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/tags.js +0 -17
- package/dist/formats/webgpu/core/cewgpu/tags.js.map +0 -1
- package/dist/formats/webgpu/core/effectPackageValidation.js +0 -1078
- package/dist/formats/webgpu/core/effectPackageValidation.js.map +0 -1
- package/docs/formats/hlsl/reference/classes/carbon-compatibility.md +0 -66
- package/docs/formats/hlsl/reference/classes/public-api.md +0 -26
- package/docs/formats/hlsl/reference/classes/tr2-effect-model.md +0 -150
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { HlslEffectBindingManifest } from '../../../hlsl/core/tr2/shader/HlslEffectBindingManifest.js';
|
|
2
|
+
import { HlslShaderBytecode } from '../../../hlsl/core/HlslShaderBytecode.js';
|
|
3
|
+
import { hlslShaderStageName } from '../../../hlsl/core/tr2/HlslRenderContextEnum.js';
|
|
4
|
+
import { runtimeDescriptionFromCarbon } from '../../../hlsl/core/carbonDescriptionToRuntime.js';
|
|
5
|
+
import { buildEffectAnalysis } from '../helpers.js';
|
|
6
|
+
import { WGSL_SET_VERSION } from '../wgsl/buildWgslSet.js';
|
|
7
|
+
import { sha256Utf8 } from '../../../../format/effect/sha256.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Derived compatibility views over a container.
|
|
11
|
+
*
|
|
12
|
+
* The chunk package stored `ANLS` and `WGSL` as documents beside the reflection
|
|
13
|
+
* they were computed from, and carried digests to detect the two disagreeing.
|
|
14
|
+
* The container stores one document, so these are **views**: functions of the
|
|
15
|
+
* records, computed on read. The class of bug the digests guarded cannot occur,
|
|
16
|
+
* because there is no second copy to drift.
|
|
17
|
+
*
|
|
18
|
+
* The analysis view is deliberately not a reimplementation. It runs
|
|
19
|
+
* `buildEffectAnalysis` — the same function the packager runs on source — over a
|
|
20
|
+
* description rebuilt by `runtimeDescriptionFromCarbon`. That is what keeps the
|
|
21
|
+
* view honest: if it were rewritten to emit the fields consumers read today, it
|
|
22
|
+
* would be free to drift from the real analysis, and nothing would notice.
|
|
23
|
+
* `carbon-analysis-adapter-corpus.test.mjs` diffs the two over every shipped
|
|
24
|
+
* permutation and finds zero differences.
|
|
25
|
+
*
|
|
26
|
+
* These views exist for `engine-webgpu`, which reads format-package JSON for
|
|
27
|
+
* Carbon reflection instead of reading `Tr2Shader`. That is a recorded layering
|
|
28
|
+
* defect and is not this port's to fix; the views keep it working unchanged
|
|
29
|
+
* while the wire format moves underneath it. They go away with that cleanup.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolves the permutation Carbon's own `GetShader()` would select with no
|
|
34
|
+
* option overrides.
|
|
35
|
+
*
|
|
36
|
+
* Carbon multiplies each axis's default option by the running product of the
|
|
37
|
+
* preceding axes' option counts. The chunk package stored a single selected
|
|
38
|
+
* body and its index; the container carries every permutation, so the view has
|
|
39
|
+
* to name a default rather than inherit one, and Carbon's own default is the
|
|
40
|
+
* only defensible choice.
|
|
41
|
+
*
|
|
42
|
+
* @param {object} container Loaded container.
|
|
43
|
+
* @returns {number} Permutation index.
|
|
44
|
+
*/
|
|
45
|
+
function defaultPermutationIndex(container) {
|
|
46
|
+
let multiplier = 1;
|
|
47
|
+
let index = 0;
|
|
48
|
+
for (const axis of container.carbon.permutations) {
|
|
49
|
+
index += axis.defaultOption * multiplier;
|
|
50
|
+
multiplier *= axis.options.length || 1;
|
|
51
|
+
}
|
|
52
|
+
return index < container.carbon.records.length ? index : 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Rebuilds the runtime effect description for one permutation.
|
|
57
|
+
*
|
|
58
|
+
* @param {object} container Loaded container.
|
|
59
|
+
* @param {number} permutationIndex Permutation index.
|
|
60
|
+
* @param {string} source Source label.
|
|
61
|
+
* @returns {object} Runtime-shaped effect description.
|
|
62
|
+
*/
|
|
63
|
+
function describeRuntime(container, permutationIndex, source) {
|
|
64
|
+
return runtimeDescriptionFromCarbon(container.GetDescription(permutationIndex), {
|
|
65
|
+
effectName: source,
|
|
66
|
+
version: container.carbon.version,
|
|
67
|
+
bytecodeFor: (stage, stageType) => new HlslShaderBytecode({
|
|
68
|
+
stageType,
|
|
69
|
+
// Carbon's six stage names, not WebGPU's three. A three-entry table
|
|
70
|
+
// reports a geometry stage as null, which the corpus caught.
|
|
71
|
+
stageName: hlslShaderStageName(stageType),
|
|
72
|
+
bytes: stage.shaderData.bytes,
|
|
73
|
+
shaderSize: stage.shaderData.size,
|
|
74
|
+
stringTableOffset: stage.shaderData.offset,
|
|
75
|
+
effectName: source
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Derives the analysis document for one permutation.
|
|
82
|
+
*
|
|
83
|
+
* One field is honestly different from the stored `ANLS` it replaces:
|
|
84
|
+
* `stages[].shaderBytecode` describes the **WGSL** program the container
|
|
85
|
+
* carries, where the stored document described the source DXBC. The container
|
|
86
|
+
* does not carry DXBC, so reproducing the old numbers would mean inventing
|
|
87
|
+
* them. Nothing in the engine's read surface uses this field; it is a
|
|
88
|
+
* diagnostic.
|
|
89
|
+
*
|
|
90
|
+
* @param {object} container Loaded container.
|
|
91
|
+
* @param {object} [options] View options.
|
|
92
|
+
* @param {string} [options.source] Source label.
|
|
93
|
+
* @param {number} [options.permutationIndex] Permutation to describe.
|
|
94
|
+
* @returns {object} Analysis document.
|
|
95
|
+
*/
|
|
96
|
+
function deriveAnalysis(container, options = {}) {
|
|
97
|
+
const source = options.source || container.sourcePath || "memory";
|
|
98
|
+
const permutationIndex = options.permutationIndex ?? defaultPermutationIndex(container);
|
|
99
|
+
const effectDescription = describeRuntime(container, permutationIndex, source);
|
|
100
|
+
return buildEffectAnalysis({
|
|
101
|
+
effectDescription,
|
|
102
|
+
bindingManifest: HlslEffectBindingManifest.fromEffectDescription(effectDescription, {
|
|
103
|
+
effectName: source
|
|
104
|
+
}),
|
|
105
|
+
effectRes: {
|
|
106
|
+
sourcePath: source,
|
|
107
|
+
m_compilerVersion: null
|
|
108
|
+
},
|
|
109
|
+
selection: {
|
|
110
|
+
bodyIndex: permutationIndex,
|
|
111
|
+
selectedOptions: container.carbon.permutations.map(axis => ({
|
|
112
|
+
name: axis.name.value,
|
|
113
|
+
value: axis.options[axis.defaultOption]?.value ?? null
|
|
114
|
+
}))
|
|
115
|
+
}
|
|
116
|
+
}, {
|
|
117
|
+
source,
|
|
118
|
+
decodeBytecode: false,
|
|
119
|
+
decodeInstructions: false
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Derives the WGSL set document for one permutation.
|
|
125
|
+
*
|
|
126
|
+
* `sourceMap` is absent rather than empty, and that is not an oversight: its
|
|
127
|
+
* offsets index DXBC bytes the container does not carry, so it is a translator
|
|
128
|
+
* diagnostic and was dropped on write. It was separately measured to suppress
|
|
129
|
+
* no sharing, so keeping it would have bought nothing either.
|
|
130
|
+
*
|
|
131
|
+
* @param {object} container Loaded container.
|
|
132
|
+
* @param {object} [options] View options.
|
|
133
|
+
* @param {number} [options.permutationIndex] Permutation to describe.
|
|
134
|
+
* @returns {object} WGSL set document.
|
|
135
|
+
*/
|
|
136
|
+
function deriveWgsl(container, options = {}) {
|
|
137
|
+
const permutationIndex = options.permutationIndex ?? defaultPermutationIndex(container);
|
|
138
|
+
const body = container.GetBackendBodyPrograms(permutationIndex);
|
|
139
|
+
const shaders = [];
|
|
140
|
+
const layouts = [];
|
|
141
|
+
const resourceTransforms = [];
|
|
142
|
+
for (const pass of body?.passes ?? []) {
|
|
143
|
+
for (const shader of pass.shaders) {
|
|
144
|
+
shaders.push({
|
|
145
|
+
key: shader.key,
|
|
146
|
+
techniqueName: shader.techniqueName,
|
|
147
|
+
passIndex: shader.passIndex,
|
|
148
|
+
stageName: shader.stageName,
|
|
149
|
+
stage: shader.stage,
|
|
150
|
+
stageType: shader.stageType,
|
|
151
|
+
entryPoint: shader.entryPoint,
|
|
152
|
+
code: shader.code,
|
|
153
|
+
...(shader.threadGroupSize ? {
|
|
154
|
+
threadGroupSize: [...shader.threadGroupSize]
|
|
155
|
+
} : {})
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
for (const layout of pass.layouts) layouts.push(layout);
|
|
159
|
+
for (const transform of pass.resourceTransforms ?? []) resourceTransforms.push(transform);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
format: "CJS_WGSL_SET",
|
|
163
|
+
formatVersion: WGSL_SET_VERSION,
|
|
164
|
+
shaders,
|
|
165
|
+
layouts,
|
|
166
|
+
...(resourceTransforms.length ? {
|
|
167
|
+
resourceTransforms
|
|
168
|
+
} : {})
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Derives the `WGSB` body-set view the chunk package used to store.
|
|
174
|
+
*
|
|
175
|
+
* `engine-webgpu` resolves a permutation's translated programs through this,
|
|
176
|
+
* which is part of the recorded layering defect -- it should read the shader,
|
|
177
|
+
* not a package document. The view keeps that path working unchanged while the
|
|
178
|
+
* wire format moves underneath it, and goes away with the cleanup.
|
|
179
|
+
*
|
|
180
|
+
* Nothing here is stored. A body's status is whether its stages carry programs,
|
|
181
|
+
* its passes are the record tree's passes, and a pass unit is that pass's
|
|
182
|
+
* shaders and layouts. Bodies are keyed by distinct stored offset, which is
|
|
183
|
+
* exactly what Carbon's alias dedupe produces.
|
|
184
|
+
*
|
|
185
|
+
* @param {object} container Loaded container.
|
|
186
|
+
* @returns {object} Body-set document.
|
|
187
|
+
*/
|
|
188
|
+
function deriveBackendBodySet(container) {
|
|
189
|
+
const bodyKeys = container.bodyKeyByOffset;
|
|
190
|
+
const passUnits = [];
|
|
191
|
+
const bodies = [];
|
|
192
|
+
const seen = new Set();
|
|
193
|
+
for (let index = 0; index < container.carbon.records.length; index += 1) {
|
|
194
|
+
const offset = container.carbon.records[index].offset;
|
|
195
|
+
if (seen.has(offset)) continue;
|
|
196
|
+
seen.add(offset);
|
|
197
|
+
const bodyKey = bodyKeys.get(offset);
|
|
198
|
+
const body = container.GetBackendBodyPrograms(index);
|
|
199
|
+
if (!body || body.status !== "translated") {
|
|
200
|
+
bodies.push({
|
|
201
|
+
bodyKey,
|
|
202
|
+
representativePermutationIndex: index,
|
|
203
|
+
status: "unsupported",
|
|
204
|
+
error: body?.error ?? "body carries no translated programs",
|
|
205
|
+
passCount: 0,
|
|
206
|
+
passes: []
|
|
207
|
+
});
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const passes = [];
|
|
211
|
+
for (const pass of body.passes) {
|
|
212
|
+
const unit = {
|
|
213
|
+
key: `unit${passUnits.length}`,
|
|
214
|
+
// Hashed from the unit's own content. The chunk body set stored
|
|
215
|
+
// this digest to detect a unit drifting from what referenced it;
|
|
216
|
+
// derived from the content it identifies, it cannot.
|
|
217
|
+
sha256: sha256Utf8(`${JSON.stringify({
|
|
218
|
+
shaders: pass.shaders,
|
|
219
|
+
layouts: pass.layouts,
|
|
220
|
+
resourceTransforms: pass.resourceTransforms ?? []
|
|
221
|
+
})}
|
|
222
|
+
`),
|
|
223
|
+
wgslSetVersion: WGSL_SET_VERSION,
|
|
224
|
+
shaders: pass.shaders,
|
|
225
|
+
layouts: pass.layouts,
|
|
226
|
+
...(pass.resourceTransforms?.length ? {
|
|
227
|
+
resourceTransforms: pass.resourceTransforms
|
|
228
|
+
} : {})
|
|
229
|
+
};
|
|
230
|
+
passUnits.push(unit);
|
|
231
|
+
passes.push({
|
|
232
|
+
passKey: pass.passKey,
|
|
233
|
+
unitKey: unit.key
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
bodies.push({
|
|
237
|
+
bodyKey,
|
|
238
|
+
representativePermutationIndex: index,
|
|
239
|
+
status: "translated",
|
|
240
|
+
error: null,
|
|
241
|
+
passCount: passes.length,
|
|
242
|
+
passes
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
format: "CJS_WGSL_BODY_SET",
|
|
247
|
+
formatVersion: 1,
|
|
248
|
+
bodyCount: bodies.length,
|
|
249
|
+
translatedBodyCount: bodies.filter(body => body.status === "translated").length,
|
|
250
|
+
passUnitCount: passUnits.length,
|
|
251
|
+
passUnits,
|
|
252
|
+
bodies
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Finds the permutation a package resolves to.
|
|
258
|
+
*
|
|
259
|
+
* A "selected" package is not a different format -- the container always carries
|
|
260
|
+
* every permutation. What makes it selected is that exactly one body was
|
|
261
|
+
* translated, so the resolved permutation is the first one whose body carries
|
|
262
|
+
* programs. When every body is translated, there is nothing to single out and
|
|
263
|
+
* Carbon's own default applies.
|
|
264
|
+
*
|
|
265
|
+
* @param {object} container Loaded container.
|
|
266
|
+
* @returns {number} Permutation index.
|
|
267
|
+
*/
|
|
268
|
+
function resolvedPermutationIndex(container) {
|
|
269
|
+
const translated = [];
|
|
270
|
+
const seen = new Set();
|
|
271
|
+
for (let index = 0; index < container.carbon.records.length; index += 1) {
|
|
272
|
+
const offset = container.carbon.records[index].offset;
|
|
273
|
+
if (seen.has(offset)) continue;
|
|
274
|
+
seen.add(offset);
|
|
275
|
+
const body = container.GetBackendBodyPrograms(index);
|
|
276
|
+
if (body?.status === "translated") translated.push(index);
|
|
277
|
+
if (translated.length > 1) return defaultPermutationIndex(container);
|
|
278
|
+
}
|
|
279
|
+
return translated.length === 1 ? translated[0] : defaultPermutationIndex(container);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Derives the `META`-shaped view the chunk package used to store.
|
|
284
|
+
*
|
|
285
|
+
* Every field here is recovered from the records rather than carried:
|
|
286
|
+
* `selectedOptions` from the resolved permutation's option indices, and
|
|
287
|
+
* `wgslSelection` from which passes and stages actually hold programs. Build-time
|
|
288
|
+
* *policy* -- `bodyMode`, `sourceIdentity`, `completeness` -- is deliberately not
|
|
289
|
+
* here: it describes how the artifact was produced, not what it is, and Carbon
|
|
290
|
+
* stores none of it.
|
|
291
|
+
*
|
|
292
|
+
* @param {object} container Loaded container.
|
|
293
|
+
* @param {object} [options] View options.
|
|
294
|
+
* @param {string} [options.source] Source label.
|
|
295
|
+
* @param {number} [options.permutationIndex] Permutation to describe.
|
|
296
|
+
* @returns {object} Metadata document.
|
|
297
|
+
*/
|
|
298
|
+
function deriveMetadata(container, options = {}) {
|
|
299
|
+
const source = options.source || container.sourcePath || "memory";
|
|
300
|
+
const permutationIndex = options.permutationIndex ?? resolvedPermutationIndex(container);
|
|
301
|
+
const variant = container.permutationGraph.variants[permutationIndex];
|
|
302
|
+
const axes = container.carbon.permutations;
|
|
303
|
+
const selectedOptions = axes.map((axis, axisIndex) => ({
|
|
304
|
+
name: axis.name.value,
|
|
305
|
+
value: axis.options[variant?.optionIndices?.[axisIndex] ?? axis.defaultOption]?.value ?? null
|
|
306
|
+
}));
|
|
307
|
+
const body = container.GetBackendBodyPrograms(permutationIndex);
|
|
308
|
+
const selectedStageKeys = (body?.passes ?? []).flatMap(pass => pass.shaders.map(shader => shader.key));
|
|
309
|
+
const passKeys = (body?.passes ?? []).map(pass => pass.passKey);
|
|
310
|
+
return {
|
|
311
|
+
effectName: source,
|
|
312
|
+
sourcePath: source,
|
|
313
|
+
bodyIndex: permutationIndex,
|
|
314
|
+
selectedOptions,
|
|
315
|
+
...(passKeys.length === 1 ? {
|
|
316
|
+
wgslSelection: {
|
|
317
|
+
mode: "explicit",
|
|
318
|
+
completePasses: true,
|
|
319
|
+
techniqueName: passKeys[0].slice(0, passKeys[0].lastIndexOf(".pass")),
|
|
320
|
+
passIndex: Number(/\.pass([0-9]+)$/u.exec(passKeys[0])?.[1] ?? 0),
|
|
321
|
+
requestedStageNames: Array.from(new Set((body?.passes ?? []).flatMap(pass => pass.shaders.map(shader => shader.stageName)))),
|
|
322
|
+
selectedStageKeys
|
|
323
|
+
}
|
|
324
|
+
} : {})
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Derives the `INFO`-shaped summary the chunk package used to store.
|
|
330
|
+
*
|
|
331
|
+
* Everything here is counted from the records rather than trusted from a stored
|
|
332
|
+
* field, which is why no digest accompanies it: a count derived from the thing
|
|
333
|
+
* it counts cannot disagree with it.
|
|
334
|
+
*
|
|
335
|
+
* @param {object} container Loaded container.
|
|
336
|
+
* @param {object} [options] View options.
|
|
337
|
+
* @param {string} [options.source] Source label.
|
|
338
|
+
* @returns {object} Info document.
|
|
339
|
+
*/
|
|
340
|
+
function deriveInfo(container, options = {}) {
|
|
341
|
+
const source = options.source || container.sourcePath || "memory";
|
|
342
|
+
const graph = container.permutationGraph;
|
|
343
|
+
return {
|
|
344
|
+
format: "CEWGPU",
|
|
345
|
+
packageKind: "tr2-effect-webgpu",
|
|
346
|
+
sourcePath: source,
|
|
347
|
+
effectVersion: container.carbon.version,
|
|
348
|
+
compilerVersion: [...container.carbon.compilerVersion],
|
|
349
|
+
permutationCount: graph.variants.length,
|
|
350
|
+
uniqueBodyCount: graph.bodies.length
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export { defaultPermutationIndex, deriveAnalysis, deriveBackendBodySet, deriveInfo, deriveMetadata, deriveWgsl, resolvedPermutationIndex };
|
|
355
|
+
//# sourceMappingURL=containerViews.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"containerViews.js","sources":["../../../../../../src/formats/webgpu/core/cewgpu/containerViews.js"],"sourcesContent":["import { HlslEffectBindingManifest } from \"../../../hlsl/core/tr2/shader/HlslEffectBindingManifest.js\";\nimport { HlslShaderBytecode } from \"../../../hlsl/core/HlslShaderBytecode.js\";\nimport { hlslShaderStageName } from \"../../../hlsl/core/tr2/HlslRenderContextEnum.js\";\nimport { runtimeDescriptionFromCarbon } from \"../../../hlsl/core/carbonDescriptionToRuntime.js\";\nimport { buildEffectAnalysis } from \"../helpers.js\";\nimport { WGSL_SET_VERSION } from \"../wgsl/buildWgslSet.js\";\nimport { sha256Utf8 } from \"../../../../format/effect/sha256.js\";\n\n/**\n * Derived compatibility views over a container.\n *\n * The chunk package stored `ANLS` and `WGSL` as documents beside the reflection\n * they were computed from, and carried digests to detect the two disagreeing.\n * The container stores one document, so these are **views**: functions of the\n * records, computed on read. The class of bug the digests guarded cannot occur,\n * because there is no second copy to drift.\n *\n * The analysis view is deliberately not a reimplementation. It runs\n * `buildEffectAnalysis` — the same function the packager runs on source — over a\n * description rebuilt by `runtimeDescriptionFromCarbon`. That is what keeps the\n * view honest: if it were rewritten to emit the fields consumers read today, it\n * would be free to drift from the real analysis, and nothing would notice.\n * `carbon-analysis-adapter-corpus.test.mjs` diffs the two over every shipped\n * permutation and finds zero differences.\n *\n * These views exist for `engine-webgpu`, which reads format-package JSON for\n * Carbon reflection instead of reading `Tr2Shader`. That is a recorded layering\n * defect and is not this port's to fix; the views keep it working unchanged\n * while the wire format moves underneath it. They go away with that cleanup.\n */\n\n/**\n * Resolves the permutation Carbon's own `GetShader()` would select with no\n * option overrides.\n *\n * Carbon multiplies each axis's default option by the running product of the\n * preceding axes' option counts. The chunk package stored a single selected\n * body and its index; the container carries every permutation, so the view has\n * to name a default rather than inherit one, and Carbon's own default is the\n * only defensible choice.\n *\n * @param {object} container Loaded container.\n * @returns {number} Permutation index.\n */\nexport function defaultPermutationIndex(container)\n{\n let multiplier = 1;\n let index = 0;\n for (const axis of container.carbon.permutations)\n {\n index += axis.defaultOption * multiplier;\n multiplier *= axis.options.length || 1;\n }\n return index < container.carbon.records.length ? index : 0;\n}\n\n/**\n * Rebuilds the runtime effect description for one permutation.\n *\n * @param {object} container Loaded container.\n * @param {number} permutationIndex Permutation index.\n * @param {string} source Source label.\n * @returns {object} Runtime-shaped effect description.\n */\nfunction describeRuntime(container, permutationIndex, source)\n{\n return runtimeDescriptionFromCarbon(container.GetDescription(permutationIndex), {\n effectName: source,\n version: container.carbon.version,\n bytecodeFor: (stage, stageType) => new HlslShaderBytecode({\n stageType,\n // Carbon's six stage names, not WebGPU's three. A three-entry table\n // reports a geometry stage as null, which the corpus caught.\n stageName: hlslShaderStageName(stageType),\n bytes: stage.shaderData.bytes,\n shaderSize: stage.shaderData.size,\n stringTableOffset: stage.shaderData.offset,\n effectName: source\n })\n });\n}\n\n/**\n * Derives the analysis document for one permutation.\n *\n * One field is honestly different from the stored `ANLS` it replaces:\n * `stages[].shaderBytecode` describes the **WGSL** program the container\n * carries, where the stored document described the source DXBC. The container\n * does not carry DXBC, so reproducing the old numbers would mean inventing\n * them. Nothing in the engine's read surface uses this field; it is a\n * diagnostic.\n *\n * @param {object} container Loaded container.\n * @param {object} [options] View options.\n * @param {string} [options.source] Source label.\n * @param {number} [options.permutationIndex] Permutation to describe.\n * @returns {object} Analysis document.\n */\nexport function deriveAnalysis(container, options = {})\n{\n const source = options.source || container.sourcePath || \"memory\";\n const permutationIndex = options.permutationIndex ?? defaultPermutationIndex(container);\n const effectDescription = describeRuntime(container, permutationIndex, source);\n\n return buildEffectAnalysis({\n effectDescription,\n bindingManifest: HlslEffectBindingManifest.fromEffectDescription(effectDescription, {\n effectName: source\n }),\n effectRes: {\n sourcePath: source,\n m_compilerVersion: null\n },\n selection: {\n bodyIndex: permutationIndex,\n selectedOptions: container.carbon.permutations.map((axis) => ({\n name: axis.name.value,\n value: axis.options[axis.defaultOption]?.value ?? null\n }))\n }\n }, { source, decodeBytecode: false, decodeInstructions: false });\n}\n\n/**\n * Derives the WGSL set document for one permutation.\n *\n * `sourceMap` is absent rather than empty, and that is not an oversight: its\n * offsets index DXBC bytes the container does not carry, so it is a translator\n * diagnostic and was dropped on write. It was separately measured to suppress\n * no sharing, so keeping it would have bought nothing either.\n *\n * @param {object} container Loaded container.\n * @param {object} [options] View options.\n * @param {number} [options.permutationIndex] Permutation to describe.\n * @returns {object} WGSL set document.\n */\nexport function deriveWgsl(container, options = {})\n{\n const permutationIndex = options.permutationIndex ?? defaultPermutationIndex(container);\n const body = container.GetBackendBodyPrograms(permutationIndex);\n const shaders = [];\n const layouts = [];\n const resourceTransforms = [];\n\n for (const pass of body?.passes ?? [])\n {\n for (const shader of pass.shaders)\n {\n shaders.push({\n key: shader.key,\n techniqueName: shader.techniqueName,\n passIndex: shader.passIndex,\n stageName: shader.stageName,\n stage: shader.stage,\n stageType: shader.stageType,\n entryPoint: shader.entryPoint,\n code: shader.code,\n ...(shader.threadGroupSize ? { threadGroupSize: [ ...shader.threadGroupSize ] } : {})\n });\n }\n for (const layout of pass.layouts) layouts.push(layout);\n for (const transform of pass.resourceTransforms ?? []) resourceTransforms.push(transform);\n }\n\n return {\n format: \"CJS_WGSL_SET\",\n formatVersion: WGSL_SET_VERSION,\n shaders,\n layouts,\n ...(resourceTransforms.length ? { resourceTransforms } : {})\n };\n}\n\n/**\n * Derives the `WGSB` body-set view the chunk package used to store.\n *\n * `engine-webgpu` resolves a permutation's translated programs through this,\n * which is part of the recorded layering defect -- it should read the shader,\n * not a package document. The view keeps that path working unchanged while the\n * wire format moves underneath it, and goes away with the cleanup.\n *\n * Nothing here is stored. A body's status is whether its stages carry programs,\n * its passes are the record tree's passes, and a pass unit is that pass's\n * shaders and layouts. Bodies are keyed by distinct stored offset, which is\n * exactly what Carbon's alias dedupe produces.\n *\n * @param {object} container Loaded container.\n * @returns {object} Body-set document.\n */\nexport function deriveBackendBodySet(container)\n{\n const bodyKeys = container.bodyKeyByOffset;\n const passUnits = [];\n const bodies = [];\n const seen = new Set();\n\n for (let index = 0; index < container.carbon.records.length; index += 1)\n {\n const offset = container.carbon.records[index].offset;\n if (seen.has(offset)) continue;\n seen.add(offset);\n\n const bodyKey = bodyKeys.get(offset);\n const body = container.GetBackendBodyPrograms(index);\n\n if (!body || body.status !== \"translated\")\n {\n bodies.push({\n bodyKey,\n representativePermutationIndex: index,\n status: \"unsupported\",\n error: body?.error ?? \"body carries no translated programs\",\n passCount: 0,\n passes: []\n });\n continue;\n }\n\n const passes = [];\n for (const pass of body.passes)\n {\n const unit = {\n key: `unit${passUnits.length}`,\n // Hashed from the unit's own content. The chunk body set stored\n // this digest to detect a unit drifting from what referenced it;\n // derived from the content it identifies, it cannot.\n sha256: sha256Utf8(`${JSON.stringify({\n shaders: pass.shaders,\n layouts: pass.layouts,\n resourceTransforms: pass.resourceTransforms ?? []\n })}\n`),\n wgslSetVersion: WGSL_SET_VERSION,\n shaders: pass.shaders,\n layouts: pass.layouts,\n ...(pass.resourceTransforms?.length\n ? { resourceTransforms: pass.resourceTransforms }\n : {})\n };\n passUnits.push(unit);\n passes.push({ passKey: pass.passKey, unitKey: unit.key });\n }\n\n bodies.push({\n bodyKey,\n representativePermutationIndex: index,\n status: \"translated\",\n error: null,\n passCount: passes.length,\n passes\n });\n }\n\n return {\n format: \"CJS_WGSL_BODY_SET\",\n formatVersion: 1,\n bodyCount: bodies.length,\n translatedBodyCount: bodies.filter((body) => body.status === \"translated\").length,\n passUnitCount: passUnits.length,\n passUnits,\n bodies\n };\n}\n\n/**\n * Finds the permutation a package resolves to.\n *\n * A \"selected\" package is not a different format -- the container always carries\n * every permutation. What makes it selected is that exactly one body was\n * translated, so the resolved permutation is the first one whose body carries\n * programs. When every body is translated, there is nothing to single out and\n * Carbon's own default applies.\n *\n * @param {object} container Loaded container.\n * @returns {number} Permutation index.\n */\nexport function resolvedPermutationIndex(container)\n{\n const translated = [];\n const seen = new Set();\n\n for (let index = 0; index < container.carbon.records.length; index += 1)\n {\n const offset = container.carbon.records[index].offset;\n if (seen.has(offset)) continue;\n seen.add(offset);\n\n const body = container.GetBackendBodyPrograms(index);\n if (body?.status === \"translated\") translated.push(index);\n if (translated.length > 1) return defaultPermutationIndex(container);\n }\n\n return translated.length === 1 ? translated[0] : defaultPermutationIndex(container);\n}\n\n/**\n * Derives the `META`-shaped view the chunk package used to store.\n *\n * Every field here is recovered from the records rather than carried:\n * `selectedOptions` from the resolved permutation's option indices, and\n * `wgslSelection` from which passes and stages actually hold programs. Build-time\n * *policy* -- `bodyMode`, `sourceIdentity`, `completeness` -- is deliberately not\n * here: it describes how the artifact was produced, not what it is, and Carbon\n * stores none of it.\n *\n * @param {object} container Loaded container.\n * @param {object} [options] View options.\n * @param {string} [options.source] Source label.\n * @param {number} [options.permutationIndex] Permutation to describe.\n * @returns {object} Metadata document.\n */\nexport function deriveMetadata(container, options = {})\n{\n const source = options.source || container.sourcePath || \"memory\";\n const permutationIndex = options.permutationIndex ?? resolvedPermutationIndex(container);\n const variant = container.permutationGraph.variants[permutationIndex];\n const axes = container.carbon.permutations;\n\n const selectedOptions = axes.map((axis, axisIndex) => ({\n name: axis.name.value,\n value: axis.options[variant?.optionIndices?.[axisIndex] ?? axis.defaultOption]?.value ?? null\n }));\n\n const body = container.GetBackendBodyPrograms(permutationIndex);\n const selectedStageKeys = (body?.passes ?? [])\n .flatMap((pass) => pass.shaders.map((shader) => shader.key));\n const passKeys = (body?.passes ?? []).map((pass) => pass.passKey);\n\n return {\n effectName: source,\n sourcePath: source,\n bodyIndex: permutationIndex,\n selectedOptions,\n ...(passKeys.length === 1\n ? {\n wgslSelection: {\n mode: \"explicit\",\n completePasses: true,\n techniqueName: passKeys[0].slice(0, passKeys[0].lastIndexOf(\".pass\")),\n passIndex: Number(/\\.pass([0-9]+)$/u.exec(passKeys[0])?.[1] ?? 0),\n requestedStageNames: Array.from(new Set(\n (body?.passes ?? []).flatMap((pass) => pass.shaders.map((shader) => shader.stageName))\n )),\n selectedStageKeys\n }\n }\n : {})\n };\n}\n\n/**\n * Derives the `INFO`-shaped summary the chunk package used to store.\n *\n * Everything here is counted from the records rather than trusted from a stored\n * field, which is why no digest accompanies it: a count derived from the thing\n * it counts cannot disagree with it.\n *\n * @param {object} container Loaded container.\n * @param {object} [options] View options.\n * @param {string} [options.source] Source label.\n * @returns {object} Info document.\n */\nexport function deriveInfo(container, options = {})\n{\n const source = options.source || container.sourcePath || \"memory\";\n const graph = container.permutationGraph;\n return {\n format: \"CEWGPU\",\n packageKind: \"tr2-effect-webgpu\",\n sourcePath: source,\n effectVersion: container.carbon.version,\n compilerVersion: [ ...container.carbon.compilerVersion ],\n permutationCount: graph.variants.length,\n uniqueBodyCount: graph.bodies.length\n };\n}\n\nexport default deriveAnalysis;\n"],"names":["defaultPermutationIndex","container","multiplier","index","axis","carbon","permutations","defaultOption","options","length","records","describeRuntime","permutationIndex","source","runtimeDescriptionFromCarbon","GetDescription","effectName","version","bytecodeFor","stage","stageType","HlslShaderBytecode","stageName","hlslShaderStageName","bytes","shaderData","shaderSize","size","stringTableOffset","offset","deriveAnalysis","sourcePath","effectDescription","buildEffectAnalysis","bindingManifest","HlslEffectBindingManifest","fromEffectDescription","effectRes","m_compilerVersion","selection","bodyIndex","selectedOptions","map","name","value","decodeBytecode","decodeInstructions","deriveWgsl","body","GetBackendBodyPrograms","shaders","layouts","resourceTransforms","pass","passes","shader","push","key","techniqueName","passIndex","entryPoint","code","threadGroupSize","layout","transform","format","formatVersion","WGSL_SET_VERSION","deriveBackendBodySet","bodyKeys","bodyKeyByOffset","passUnits","bodies","seen","Set","has","add","bodyKey","get","status","representativePermutationIndex","error","passCount","unit","sha256","sha256Utf8","JSON","stringify","wgslSetVersion","passKey","unitKey","bodyCount","translatedBodyCount","filter","passUnitCount","resolvedPermutationIndex","translated","deriveMetadata","variant","permutationGraph","variants","axes","axisIndex","optionIndices","selectedStageKeys","flatMap","passKeys","wgslSelection","mode","completePasses","slice","lastIndexOf","Number","exec","requestedStageNames","Array","from","deriveInfo","graph","packageKind","effectVersion","compilerVersion","permutationCount","uniqueBodyCount"],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { WebgpuReadError } from '../errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structural validation for a loaded WebGPU effect container.
|
|
5
|
+
*
|
|
6
|
+
* This replaces `validateEffectPackageEnvelope`, which was 1762 lines. Most of
|
|
7
|
+
* that is **deleted rather than translated**, and the reason matters: those
|
|
8
|
+
* checks were not format invariants. The chunk container shattered one logical
|
|
9
|
+
* tree into flat string-keyed arrays across `INFO`, `META`, `ANLS`, `WGSL`,
|
|
10
|
+
* `PGRF` and `WGSB`, each holding a projection of the same effect, and roughly
|
|
11
|
+
* 600 lines asserted that the projections still agreed with each other. A record
|
|
12
|
+
* layout makes that question unaskable: containment replaces reference, position
|
|
13
|
+
* replaces key, and the count word before an array replaces `Array.isArray`.
|
|
14
|
+
*
|
|
15
|
+
* What is deliberately **not** re-checked here, because phase 1 already enforces
|
|
16
|
+
* it and checking twice means two places to keep correct:
|
|
17
|
+
*
|
|
18
|
+
* - count caps, arena containment, offset-table density and positional indexing,
|
|
19
|
+
* and the version range — `CjsCarbonEffectReader`;
|
|
20
|
+
* - every sized record parsing to exactly its declared end — Rule 1, in the
|
|
21
|
+
* record codec and the block codec;
|
|
22
|
+
* - duplicate stage type within a pass, and stage-type range — the shape adapter
|
|
23
|
+
* fails closed on both, which is where a runtime description is built.
|
|
24
|
+
*
|
|
25
|
+
* What remains is the one thing that is genuinely this layer's: the container
|
|
26
|
+
* admits all six of Carbon's stage types by design, and WebGPU can express three.
|
|
27
|
+
* That restriction belongs to the backend, not to the container — the Carbon
|
|
28
|
+
* region is backend-invariant, and a container that admitted only three would not
|
|
29
|
+
* be Carbon's container.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** Stage types WebGPU can express, by Carbon's `InputStageType` numbering. */
|
|
33
|
+
const WEBGPU_STAGE_TYPES = new Set([0, 1, 2]);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validates a loaded container for WebGPU consumption.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} container Loaded `CewgpuContainer`.
|
|
39
|
+
* @param {object} [options] Validation options.
|
|
40
|
+
* @param {string} [options.source] Source label for diagnostics.
|
|
41
|
+
* @throws {WebgpuReadError} When the container cannot serve WebGPU.
|
|
42
|
+
*/
|
|
43
|
+
function validateEffectContainer(container, options = {}) {
|
|
44
|
+
const source = options.source || container.sourcePath || "memory";
|
|
45
|
+
if (!container?.IsGood()) {
|
|
46
|
+
throw new WebgpuReadError("CEWGPU container is not readable", {
|
|
47
|
+
source,
|
|
48
|
+
cause: container?.readError ?? null
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (!container.carbon.records.length) {
|
|
52
|
+
throw new WebgpuReadError("CEWGPU container declares no permutation bodies", {
|
|
53
|
+
source
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// One check per distinct stored body. Aliased rows share a blob, so checking
|
|
58
|
+
// per permutation would re-check identical bytes up to twenty times over on
|
|
59
|
+
// the effects that alias hardest.
|
|
60
|
+
const checked = new Set();
|
|
61
|
+
for (let index = 0; index < container.carbon.records.length; index += 1) {
|
|
62
|
+
const offset = container.carbon.records[index].offset;
|
|
63
|
+
if (checked.has(offset)) continue;
|
|
64
|
+
checked.add(offset);
|
|
65
|
+
const description = container.GetDescription(index);
|
|
66
|
+
for (const technique of description.techniques) {
|
|
67
|
+
for (const [passIndex, pass] of technique.passes.entries()) {
|
|
68
|
+
for (const stage of pass.stages) {
|
|
69
|
+
// A stage carrying no program is reflection-only: the body
|
|
70
|
+
// is known, the translation is not, and the emitter says so
|
|
71
|
+
// with a zero-length payload. Those are legitimate — 107
|
|
72
|
+
// shipped body-passes carry a geometry stage — so the rule
|
|
73
|
+
// is about stages with a program, not about stages.
|
|
74
|
+
if (stage.shaderData.size === 0) continue;
|
|
75
|
+
if (!WEBGPU_STAGE_TYPES.has(stage.type)) {
|
|
76
|
+
throw new WebgpuReadError(`CEWGPU container carries a program for stage type ${stage.type}, ` + "which WebGPU cannot express", {
|
|
77
|
+
source,
|
|
78
|
+
permutationIndex: index,
|
|
79
|
+
pass: `${technique.name.value}.pass${passIndex}`,
|
|
80
|
+
stageType: stage.type
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { validateEffectContainer };
|
|
90
|
+
//# sourceMappingURL=validateContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateContainer.js","sources":["../../../../../../src/formats/webgpu/core/cewgpu/validateContainer.js"],"sourcesContent":["import { WebgpuReadError } from \"../errors.js\";\n\n/**\n * Structural validation for a loaded WebGPU effect container.\n *\n * This replaces `validateEffectPackageEnvelope`, which was 1762 lines. Most of\n * that is **deleted rather than translated**, and the reason matters: those\n * checks were not format invariants. The chunk container shattered one logical\n * tree into flat string-keyed arrays across `INFO`, `META`, `ANLS`, `WGSL`,\n * `PGRF` and `WGSB`, each holding a projection of the same effect, and roughly\n * 600 lines asserted that the projections still agreed with each other. A record\n * layout makes that question unaskable: containment replaces reference, position\n * replaces key, and the count word before an array replaces `Array.isArray`.\n *\n * What is deliberately **not** re-checked here, because phase 1 already enforces\n * it and checking twice means two places to keep correct:\n *\n * - count caps, arena containment, offset-table density and positional indexing,\n * and the version range — `CjsCarbonEffectReader`;\n * - every sized record parsing to exactly its declared end — Rule 1, in the\n * record codec and the block codec;\n * - duplicate stage type within a pass, and stage-type range — the shape adapter\n * fails closed on both, which is where a runtime description is built.\n *\n * What remains is the one thing that is genuinely this layer's: the container\n * admits all six of Carbon's stage types by design, and WebGPU can express three.\n * That restriction belongs to the backend, not to the container — the Carbon\n * region is backend-invariant, and a container that admitted only three would not\n * be Carbon's container.\n */\n\n/** Stage types WebGPU can express, by Carbon's `InputStageType` numbering. */\nconst WEBGPU_STAGE_TYPES = new Set([ 0, 1, 2 ]);\n\n/**\n * Validates a loaded container for WebGPU consumption.\n *\n * @param {object} container Loaded `CewgpuContainer`.\n * @param {object} [options] Validation options.\n * @param {string} [options.source] Source label for diagnostics.\n * @throws {WebgpuReadError} When the container cannot serve WebGPU.\n */\nexport function validateEffectContainer(container, options = {})\n{\n const source = options.source || container.sourcePath || \"memory\";\n\n if (!container?.IsGood())\n {\n throw new WebgpuReadError(\"CEWGPU container is not readable\", {\n source,\n cause: container?.readError ?? null\n });\n }\n\n if (!container.carbon.records.length)\n {\n throw new WebgpuReadError(\"CEWGPU container declares no permutation bodies\", { source });\n }\n\n // One check per distinct stored body. Aliased rows share a blob, so checking\n // per permutation would re-check identical bytes up to twenty times over on\n // the effects that alias hardest.\n const checked = new Set();\n\n for (let index = 0; index < container.carbon.records.length; index += 1)\n {\n const offset = container.carbon.records[index].offset;\n if (checked.has(offset)) continue;\n checked.add(offset);\n\n const description = container.GetDescription(index);\n\n for (const technique of description.techniques)\n {\n for (const [ passIndex, pass ] of technique.passes.entries())\n {\n for (const stage of pass.stages)\n {\n // A stage carrying no program is reflection-only: the body\n // is known, the translation is not, and the emitter says so\n // with a zero-length payload. Those are legitimate — 107\n // shipped body-passes carry a geometry stage — so the rule\n // is about stages with a program, not about stages.\n if (stage.shaderData.size === 0) continue;\n\n if (!WEBGPU_STAGE_TYPES.has(stage.type))\n {\n throw new WebgpuReadError(\n `CEWGPU container carries a program for stage type ${stage.type}, `\n + \"which WebGPU cannot express\",\n {\n source,\n permutationIndex: index,\n pass: `${technique.name.value}.pass${passIndex}`,\n stageType: stage.type\n }\n );\n }\n }\n }\n }\n }\n}\n\nexport default validateEffectContainer;\n"],"names":["WEBGPU_STAGE_TYPES","Set","validateEffectContainer","container","options","source","sourcePath","IsGood","WebgpuReadError","cause","readError","carbon","records","length","checked","index","offset","has","add","description","GetDescription","technique","techniques","passIndex","pass","passes","entries","stage","stages","shaderData","size","type","permutationIndex","name","value","stageType"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAMA,kBAAkB,GAAG,IAAIC,GAAG,CAAC,CAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAE,CAAC;;AAE/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,uBAAuBA,CAACC,SAAS,EAAEC,OAAO,GAAG,EAAE,EAC/D;EACI,MAAMC,MAAM,GAAGD,OAAO,CAACC,MAAM,IAAIF,SAAS,CAACG,UAAU,IAAI,QAAQ;AAEjE,EAAA,IAAI,CAACH,SAAS,EAAEI,MAAM,EAAE,EACxB;AACI,IAAA,MAAM,IAAIC,eAAe,CAAC,kCAAkC,EAAE;MAC1DH,MAAM;AACNI,MAAAA,KAAK,EAAEN,SAAS,EAAEO,SAAS,IAAI;AACnC,KAAC,CAAC;AACN,EAAA;EAEA,IAAI,CAACP,SAAS,CAACQ,MAAM,CAACC,OAAO,CAACC,MAAM,EACpC;AACI,IAAA,MAAM,IAAIL,eAAe,CAAC,iDAAiD,EAAE;AAAEH,MAAAA;AAAO,KAAC,CAAC;AAC5F,EAAA;;AAEA;AACA;AACA;AACA,EAAA,MAAMS,OAAO,GAAG,IAAIb,GAAG,EAAE;AAEzB,EAAA,KAAK,IAAIc,KAAK,GAAG,CAAC,EAAEA,KAAK,GAAGZ,SAAS,CAACQ,MAAM,CAACC,OAAO,CAACC,MAAM,EAAEE,KAAK,IAAI,CAAC,EACvE;IACI,MAAMC,MAAM,GAAGb,SAAS,CAACQ,MAAM,CAACC,OAAO,CAACG,KAAK,CAAC,CAACC,MAAM;AACrD,IAAA,IAAIF,OAAO,CAACG,GAAG,CAACD,MAAM,CAAC,EAAE;AACzBF,IAAAA,OAAO,CAACI,GAAG,CAACF,MAAM,CAAC;AAEnB,IAAA,MAAMG,WAAW,GAAGhB,SAAS,CAACiB,cAAc,CAACL,KAAK,CAAC;AAEnD,IAAA,KAAK,MAAMM,SAAS,IAAIF,WAAW,CAACG,UAAU,EAC9C;AACI,MAAA,KAAK,MAAM,CAAEC,SAAS,EAAEC,IAAI,CAAE,IAAIH,SAAS,CAACI,MAAM,CAACC,OAAO,EAAE,EAC5D;AACI,QAAA,KAAK,MAAMC,KAAK,IAAIH,IAAI,CAACI,MAAM,EAC/B;AACI;AACA;AACA;AACA;AACA;AACA,UAAA,IAAID,KAAK,CAACE,UAAU,CAACC,IAAI,KAAK,CAAC,EAAE;UAEjC,IAAI,CAAC9B,kBAAkB,CAACiB,GAAG,CAACU,KAAK,CAACI,IAAI,CAAC,EACvC;YACI,MAAM,IAAIvB,eAAe,CACrB,CAAA,kDAAA,EAAqDmB,KAAK,CAACI,IAAI,CAAA,EAAA,CAAI,GACjE,6BAA6B,EAC/B;cACI1B,MAAM;AACN2B,cAAAA,gBAAgB,EAAEjB,KAAK;cACvBS,IAAI,EAAE,GAAGH,SAAS,CAACY,IAAI,CAACC,KAAK,CAAA,KAAA,EAAQX,SAAS,CAAA,CAAE;cAChDY,SAAS,EAAER,KAAK,CAACI;AACrB,aACJ,CAAC;AACL,UAAA;AACJ,QAAA;AACJ,MAAA;AACJ,IAAA;AACJ,EAAA;AACJ;;;;"}
|
|
@@ -9,19 +9,20 @@ import { buildWgslSet } from './wgsl/buildWgslSet.js';
|
|
|
9
9
|
import { buildResourceTransformPlan } from './wgsl/buildResourceTransformPlan.js';
|
|
10
10
|
import { sha256Utf8, sha256Bytes } from '../../../format/effect/sha256.js';
|
|
11
11
|
import { selectEffectStages } from './packageEffectSelection.js';
|
|
12
|
+
import { compareUtf8 } from '../../../format/compareUtf8.js';
|
|
12
13
|
import { isParticleClearEffectCandidate, preflightParticleClearEffectProfile, particleClearEffectProofFor } from './wgsl/lowerParticleClearComputePrograms.js';
|
|
13
14
|
|
|
14
15
|
const EFFECT_BACKEND_BODY_SET_CHUNK = "WGSB";
|
|
15
16
|
const EFFECT_BACKEND_BODY_SET_FORMAT = "CJS_WGSL_BODY_SET";
|
|
16
17
|
const EFFECT_BACKEND_BODY_SET_VERSION = 1;
|
|
17
18
|
|
|
18
|
-
/**
|
|
19
|
-
* One translation unit is exactly one pass of one body: the binding plan, the
|
|
20
|
-
* resource-transform plan, and every stage's emitted WGSL are derived together.
|
|
21
|
-
* Bodies that share an identical pass signature therefore share one unit.
|
|
22
|
-
*
|
|
23
|
-
* @param {object} pass Pass entry carrying its ordered stage records.
|
|
24
|
-
* @returns {string} Stable signature for the pass translation unit.
|
|
19
|
+
/**
|
|
20
|
+
* One translation unit is exactly one pass of one body: the binding plan, the
|
|
21
|
+
* resource-transform plan, and every stage's emitted WGSL are derived together.
|
|
22
|
+
* Bodies that share an identical pass signature therefore share one unit.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} pass Pass entry carrying its ordered stage records.
|
|
25
|
+
* @returns {string} Stable signature for the pass translation unit.
|
|
25
26
|
*/
|
|
26
27
|
function passUnitSignature(pass) {
|
|
27
28
|
return JSON.stringify({
|
|
@@ -33,7 +34,7 @@ function passUnitSignature(pass) {
|
|
|
33
34
|
// An effect profile changes emission, so two otherwise identical
|
|
34
35
|
// passes must not share one unit when their proofs differ.
|
|
35
36
|
effectProfileProof: stage.effectProfileProof ? sha256Utf8(JSON.stringify(stage.effectProfileProof)) : null
|
|
36
|
-
})).sort((left, right) => left.stageName
|
|
37
|
+
})).sort((left, right) => compareUtf8(left.stageName, right.stageName))
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
function collectBodyStageBytecode(effectDescription) {
|
|
@@ -156,19 +157,19 @@ function translatePassUnit(pass, programForKey, source, bindingPolicy) {
|
|
|
156
157
|
})));
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
/**
|
|
160
|
-
* Translate every unique source body into backend programs, layouts, and
|
|
161
|
-
* resource transforms, sharing one translation unit between bodies whose pass
|
|
162
|
-
* is byte-for-byte identical.
|
|
163
|
-
*
|
|
160
|
+
/**
|
|
161
|
+
* Translate every unique source body into backend programs, layouts, and
|
|
162
|
+
* resource transforms, sharing one translation unit between bodies whose pass
|
|
163
|
+
* is byte-for-byte identical.
|
|
164
|
+
*
|
|
164
165
|
* A body that cannot be lowered is retained as an explicitly unsupported
|
|
165
|
-
* record.
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* @param {object} effectRes Loaded version-15 `Tr2EffectRes`.
|
|
169
|
-
* @param {object} permutationGraph Validated `PGRF` document.
|
|
170
|
-
* @param {object} [options] Source label, stage selection, and binding policy.
|
|
171
|
-
* @returns {object} Frozen `CJS_WGSL_BODY_SET` document.
|
|
166
|
+
* in-memory record carrying its reason. Portable source reflection is built
|
|
167
|
+
* separately from the same effect; this body-set document does not store it.
|
|
168
|
+
*
|
|
169
|
+
* @param {object} effectRes Loaded version-15 `Tr2EffectRes`.
|
|
170
|
+
* @param {object} permutationGraph Validated `PGRF` document.
|
|
171
|
+
* @param {object} [options] Source label, stage selection, and binding policy.
|
|
172
|
+
* @returns {object} Frozen `CJS_WGSL_BODY_SET` document.
|
|
172
173
|
*/
|
|
173
174
|
function buildEffectBackendBodySet(effectRes, permutationGraph, options = {}) {
|
|
174
175
|
const source = options.source || "memory";
|