bundleVaryingLocations function
A location per varying name, agreeing with engine's.
Computed over both manifests, then held against the engine's alone. Throws WgslPrepareException when the bundle would move one of the engine's varyings: the failure is a refusal to pack rather than a section that would compile and read the wrong slot.
Implementation
Map<String, int> bundleVaryingLocations(
ShaderSet engine,
Iterable<BundleStageSource> stages,
) {
final theirs = <Set<String>>[
for (final entry in engine.stages.values)
scanVaryings(
_resolveEngine(engine, entry.file),
from: entry.file,
fragment: entry.fragment,
),
];
final ours = <Set<String>>[
for (final stage in stages)
scanVaryings(stage.resolved, from: stage.file, fragment: stage.fragment),
];
final engineOnly = assignVaryingLocations(theirs);
final together = assignVaryingLocations(<Set<String>>[...theirs, ...ours]);
for (final entry in engineOnly.entries) {
if (together[entry.key] == entry.value) continue;
throw WgslPrepareException(
'this bundle moves the engine\'s varying "${entry.key}" from location '
'${entry.value} to ${together[entry.key]}. A stage packed here is paired '
'with a stage the engine already compiled, and WebGPU joins the two by '
'location alone, so the numbering cannot be renegotiated by a bundle. '
'A varying declared beside the engine\'s in one stage joins their '
'family and renumbers it — give it a name of its own, or declare it in '
'a stage that shares nothing with the engine\'s.',
);
}
return together;
}